web-dev-qa-db-ja.com

ビュークラスからバインディングを取得する

変数を受け取るデータバインドレイアウトのCustomViewクラスがあります。 CustomViewを含むレイアウトで、属性をCustomViewに渡し、そのCustomViewにその属性を独自のレイアウトのバインディングに渡してもらいたいと思います。これが私が持っているものです:

public class CustomView extends LinearLayout
{
public CustomView(Context inContext, AttributeSet inAttrs)
{
    super(inContext, inAttrs);

    inflate(inContext, R.layout.custom_view, null);
}



@BindingAdapter({"app:variable"})
public static void SetVariable(CustomView inCustomView, VariableType inMyVariable)
{
    CustomViewBinding binding = DataBindingUtil.getBinding(inCustomView);

    binding.setMyVariable(inMyVariable);
}
}

これは、ビューからバインディングを抽出しようとするとクラッシュします。これも可能ですか?スタックトレースは次のとおりです。

Java.lang.NullPointerException: Attempt to invoke virtual method 'void xxx.databinding.CustomViewBinding.setVariableType(xxx.VariableType)' on a null object reference
                                                                            at xxx.CustomView.SetDynamicList(CustomView.Java:32)
                                                                            at xxx.MyFragmentBinding.executeBindings(MyFragmentBinding.Java:116)
                                                                            at Android.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.Java:350)
                                                                            at Android.databinding.ViewDataBinding$6.run(ViewDataBinding.Java:167)
                                                                            at Android.databinding.ViewDataBinding$7.doFrame(ViewDataBinding.Java:233)
                                                                            at Android.view.Choreographer$CallbackRecord.run(Choreographer.Java:856)
                                                                            at Android.view.Choreographer.doCallbacks(Choreographer.Java:670)
                                                                            at Android.view.Choreographer.doFrame(Choreographer.Java:603)
                                                                            at Android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.Java:844)
                                                                            at Android.os.Handler.handleCallback(Handler.Java:739)
                                                                            at Android.os.Handler.dispatchMessage(Handler.Java:95)
                                                                            at Android.os.Looper.loop(Looper.Java:148)
                                                                            at Android.app.ActivityThread.main(ActivityThread.Java:5417)
                                                                            at Java.lang.reflect.Method.invoke(Native Method)
                                                                            at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:726)
                                                                            at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:616)

そして私が変更した場合

DataBindingUtil.getBinding(inCustomView)

DataBindingUtil.bind(inCustomView)

それから私はこれを手に入れます:

Java.lang.IllegalArgumentException: View is not a binding layout
                                                                            at Android.databinding.DataBindingUtil.bind(DataBindingUtil.Java:166)
                                                                            at Android.databinding.DataBindingUtil.bind(DataBindingUtil.Java:140)
                                                                            at xxx.CustomView.SetDynamicList(CustomView.Java:30)
                    -                                                        at xxx.databinding.MyFragmentBinding.executeBindings(MyFragmentBinding.Java:116)
                                                                            at Android.databinding.ViewDataBinding.executePendingBindings(ViewDataBinding.Java:350)
                                                                            at Android.databinding.ViewDataBinding$6.run(ViewDataBinding.Java:167)
                                                                            at Android.databinding.ViewDataBinding$7.doFrame(ViewDataBinding.Java:233)
                                                                            at Android.view.Choreographer$CallbackRecord.run(Choreographer.Java:856)
                                                                            at Android.view.Choreographer.doCallbacks(Choreographer.Java:670)
                                                                            at Android.view.Choreographer.doFrame(Choreographer.Java:603)
                                                                            at Android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.Java:844)
                                                                            at Android.os.Handler.handleCallback(Handler.Java:739)
                                                                            at Android.os.Handler.dispatchMessage(Handler.Java:95)
                                                                            at Android.os.Looper.loop(Looper.Java:148)
                                                                            at Android.app.ActivityThread.main(ActivityThread.Java:5417)
                                                                            at Java.lang.reflect.Method.invoke(Native Method)
                                                                            at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:726)
                                                                            at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:616)

これは、レイアウトファイルがデータバインディング用にフォーマットされていないことを意味している可能性がありますが、フォーマットされています。レイアウト要素と、変数などを含むデータ要素があります。

11
KairisCharm

データバインディングを作成するには、インフレートされたビューをバインドする必要があります。あなたの例では、レイアウトのcontainerをバインドしています。

これは、いくつかの方法で実行できます。最も簡単なのは、インフレの一部としてそれをバインドすることです。

public class CustomView extends LinearLayout
{
  CustomViewBinding mBinding;
  public CustomView(Context inContext, AttributeSet inAttrs)
  {
    super(inContext, inAttrs);
    LayoutInflater inflater = LayoutInflater.from(inContext);
    // I assume you want it inflated into this ViewGroup
    mBinding = CustomViewBinding.inflate(inflater, this, true);
  }

  public void setVariable(CustomView inCustomView, VariableType inMyVariable) {
    mBinding.setVariable(inMyVariable);
  }
  ...
}

カスタムビューの一部としてセッターが必要ない場合を除いて、バインディングアダプターは実際には必要ありません。その場合でも、バインディングを取得する方法が必要であるため、次のようなものを追加する必要があります。

public CustomViewBinding getBinding() { return mBinding; }

バインディングアダプターが機能するようにします。

LinearLayoutの内容がすべてインフレータブルビューからのものであることがわかっている場合は、次のようなバインディングアダプターを使用できます。

@BindingAdapter({"app:variable"})
public static void setVariable(CustomView inCustomView, VariableType inMyVariable)
{
    if (inCustomView.getChildCount() == 0) {
      return;
    }
    View boundView = inCustomView.getChildAt(0);
    CustomViewBinding binding = DataBindingUtil.getBinding(boundView);

    binding.setMyVariable(inMyVariable);
}

カスタムビューがあまりカスタムではない場合は、レイアウトを直接含めることができます。

<include layout="@layout/custom_view" app:variable="@{myVariableValue}"/>

もちろん、LinearLayoutをcustom_view.xmlに移動する必要があります。

21
George Mount

基本的に、これは私にとってどのように機能したかです:

XML:

<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/containerView"
xmlns:tools="http://schemas.Android.com/tools">

.....


</layout>

Javaクラス:

GeneralOverviewBinding binding = DataBindingUtil.bind((findViewById(R.id.containerView)));

これは基本的に、指定されたレイアウトルートのバインディングを返すか、存在しない場合はバインディングを作成します。

5
Sindhu