我的情况是我有一个片段,其文本字段将由X1Object或X2Object填充,它们都实现了接口IXObject并扩展了Android DataBinding库提供的BaseObservable类,但包含其他不同的字段和行为。 IXObject包含getter和setter的方法。
public interface IXObject {
void setName(String name);
String getName();
}
public class X1Object extends BaseObservable implements IXObject {
private String name;
@Override
@Bindable
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
}
public class X2Object extends BaseObservable implements IXObject {...}
然后我尝试使用Android DataBinding为片段使用单个布局文件。布局如下所示:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="xObject" type="com.test.x.model.IXObject"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{xObject.name}"/>
</LinearLayout>
</layout>
在片段类中,我正在应用绑定:
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
MyFragmentBinding binding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false);
View view = binding.getRoot();
IXObject xobj = new X1Object();
binding.setXObject(xobject);
return view;
}
不幸的是,使用IXObject作为数据绑定引用,从不调用BaseObservable类中的方法“addOnPropertyChangedCallback”。
直接使用X1Object在布局文件和绑定类中进行绑定,一切都很完美。
您能帮助我实现使用界面进行绑定的目标吗?
谢谢。
答案 0 :(得分:2)
我也找不到使用界面的方法,但我认为你可以像这样使用Abstract类。
public abstract class IXObject extends BaseObservable {
public abstract void setName(String name);
@Bindable
public abstract String getName();
}
public class X1Object extends IXObject {
private String name;
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
notifyPropertyChanged(BR.name);
}
}
final IXObject xobj = new X1Object();
xobj.setName("nguyen");
binding.setXObject(xobj);
答案 1 :(得分:1)
在布局文件中声明变量时,必须从字面上接受它。接口不是对象。我知道Java支持通用的内联对象,您可以在其中声明接口,就好像它是一个对象一样,但是通常它们不是对象。
因此,当您说到布局文件使用接口类型的变量时,由于它不是对象,因此它实际上不能做很多事情。
您会注意到并讨厌Android数据绑定的一件事是它无法推断类型。因此,如果您尝试使用实现类来设置变量,但希望通过接口来实现它,那么您将没有任何运气。
您需要指定将使用的类,而不是这些类继承自的接口。另一个答案指出,如果您的基类具有必要的方法,则可以利用基类。
另外请注意,您只需将绑定放在私有成员变量上,它仍然会自动通过getter和setter方法。
您唯一可以做的另一件事是创建一个适配器,该适配器使用接口或您的接口,甚至使用Any强制转换,并为您设置名称。在您已经成长的适配器类中,还需要一个适配器,但是至少他们是直接这样做的。
答案 2 :(得分:0)
我想我找到了问题的根源。根据数据绑定文档,布局中设置的每个变量都必须实现Observable接口:
在编译时检查变量类型,因此如果变量实现了Observable或者是一个可观察的集合,那么它应该反映在类型中。如果变量是没有实现Observable *接口的基类或接口,则不会观察到变量!
因此没有机会使用界面。我必须使用上面答案中提到的抽象类。
答案 3 :(得分:0)
只需在界面内使用@get:Bindable
而不是@Bindable
。
而是改用LiveData:https://developer.android.com/topic/libraries/data-binding/architecture