从视图类获取绑定 [英] Get binding from view class
问题描述
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:尝试调用虚方法void 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)
在android.databinding.ViewDataBinding $ 6.run(ViewDataBinding.java:167)
在android.databinding.ViewDataBinding $ 7.doFrame(ViewDataBinding。 java:233)
在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)
在android.app.ActivityThread.main(ActivityThread.java:5417)
在java.lang.reflect.Method.invoke(本机方法)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller。 run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
如果我更改
DataBindingUtil.getBinding(inCustomView)
to
DataBindingUtil。 bind(inCustomView)
然后我得到这个:
java.lang.IllegalArgumentException:View不是绑定布局
在android.databinding.DataBindingUtil.bind(DataBindingUtil.java:166)
在android.databinding.DataBindingUtil.bind(DataBindingUtil.java:140)
在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)
在android.databinding.ViewDataBinding $ 7.doFrame(ViewDataBinding.jav a:233)
在android.view.Choreographer $ CallbackRecord.run(Choreographer.java:856)
在android.view.Choreographer.doCallbacks(Choreographer.java:670)
在android .view.Choreographer.doFrame(Choreographer.java:603)
在android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:844)
在android.os.Handler.handleCallback(Handler.java :739)
在android.os.Handler.dispatchMessage(Handler.java:95)
在android.os.Looper.loop(Loope r.java:148)
在android.app.ActivityThread.main(ActivityThread.java:5417)
在java.lang.reflect.Method.invoke(本机方法)
在com。 android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
这可能意味着布局文件未被格式化为数据绑定,但它是。它有布局元素,数据元素与变量和一切。
您必须绑定膨胀的视图创建数据捆绑。在您的示例中,您将绑定布局的容器。
您可以通过多种方式执行此操作。最简单的方法是将它作为通货膨胀的一部分来绑定:
public class CustomView extends LinearLayout
{
CustomViewBinding mBinding;
public CustomView(Context inContext,AttributeSet inAttrs)
{
super(inContext,inAttrs);
LayoutInflater inflater = LayoutInflater.from(inContext);
//我假设你想要膨胀到这个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){
返回;
}
查看boundView = inCustomView.getChildAt(0);
CustomViewBinding binding = DataBindingUtil.getBinding(boundView);
binding.setMyVariable(inMyVariable);
}
如果您的自定义视图不是很自定义,您可以简单地包含布局直接:
< include layout =@ layout / custom_viewapp:variable =@ {myVariableValue}/>
当然,您必须将LinearLayout移动到custom_view.xml中。
I have a CustomView class with a databound layout that takes a variable. In the layout that contains the CustomView, I want to pass an attribute into the CustomView, and have that CustomView pass that attribute into its own layout's binding. Here's what I have:
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);
}
}
This crashes trying to extract the binding from the view. Is this even possible? Here is the stack trace:
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)
And if I change
DataBindingUtil.getBinding(inCustomView)
to
DataBindingUtil.bind(inCustomView)
then I get this:
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)
This might imply that the layout file is not formatted for databinding, but it is. It has the layout element, and the data element with variables and everything.
You must bind the inflated view to create the data binding. In your example, you're binding the container of the layout.
You can do this in several ways. The easiest is to bind it as part of inflation:
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);
}
...
}
You don't really need a binding adapter unless you don't want the setter as part of your custom view. In that case, you'll still need a way to get the binding, so you'll need to add something like this:
public CustomViewBinding getBinding() { return mBinding; }
so that your binding adapter works.
If you know that the LinearLayout contents are all going to be from the inflated view, you can use a binding adapter like this:
@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);
}
If your custom view isn't very custom, you can simply include your layout directly:
<include layout="@layout/custom_view" app:variable="@{myVariableValue}"/>
You would, of course, have to move the LinearLayout into the custom_view.xml.
这篇关于从视图类获取绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!