双向数据绑定(在xml中),ObservableField,BaseObservable,双向数据绑定应使用哪一个? [英] Two-way databinding(in xml), ObservableField, BaseObservable , which one I should use for the two-way databinding?
问题描述
我使用数据绑定已有一段时间,即使现在JDK 8和API 24都无法使用它.我仍然找到一种以更简单的方式使用数据绑定的方法.但是,当我使用以下方法进行精确的双向数据绑定时(在我看来,双向数据绑定就是这样的事情(
I have used data-binding for a while, even now it is not available for JDK 8 and API 24 now. I still find a way to use the data binding in a easier way. But when I use the following way to do the exact two-way data binding(In my mind, the two-way data binding is the thing like here(What is two way binding?), somethings strange is happened.
1.双向数据绑定(在xml中)
android:text="@={testStr}"
This is not mentioned in the official documentation(https://developer.android.com/topic/libraries/data-binding/index.html, this page is usually updated, may be it is changed now). But it is available to bind the variable to the xml.
2.属性的ObservableField
此处的示例( https://developer.android. com/topic/libraries/data-binding/index.html#observablefields )
private static class User {
public final ObservableField<String> firstName =
new ObservableField<>();
public final ObservableField<String> lastName =
new ObservableField<>();
public final ObservableInt age = new ObservableInt();
}
3.将模型类扩展到BaseObservable
private static class User extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}
必须将模型类扩展到BaseObservable 类,并且getter方法必须用"@ Bindable" 进行注释,并且setter方法需要调用该方法 notifyPropertyChange(),在绑定xml中具有相应的命名.
The model class must be extended to the BaseObservable class, and also the getter method must be annotated with "@Bindable" and the setter method need to call the method notifyPropertyChange() with corresponding naming in the binding xml.
我的问题是,我想知道三种装订方法的缺点和优点.当然,我知道第一个会更容易.但是有一段时间我在文档和某些网站中找到了.它在下一刻消失了.官方文档已更改,没有任何明确的声明.我仍然想知道我应该使用第一种方法,所以我必须准备更改方法2或3.
Student_XML2WAY.java
Student_XML2WAY.java
public class Student_XML2WAY {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int pAge) {
age = pAge;
}
public String getName() {
return name;
}
public void setName(String pName) {
name = pName;
}
}
Student_ObserField.java
Student_ObserField.java
public class Student_ObserField {
private ObservableInt age;
private ObservableField<String> name;
public Student_ObserField() {
age = new ObservableInt();
name = new ObservableField<>();
}
public ObservableInt getAge() {
return age;
}
public ObservableField<String> getName() {
return name;
}
}
Student_Extend.java
Student_Extend.java
public class Student_Extend extends BaseObservable{
private int age;
private String name;
@Bindable
public int getAge() {
return age;
}
public void setAge(int pAge) {
age = pAge;
notifyPropertyChanged(BR.student3);
}
@Bindable
public String getName() {
return name;
}
public void setName(String pName) {
name = pName;
notifyPropertyChanged(BR.student3);
}
}
activity_main.xml
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="student1"
type="example.com.testerapplication.sp.bean.Student_XML2WAY"/>
<variable
name="student2"
type="example.com.testerapplication.sp.bean.Student_ObserField"/>
<variable
name="student3"
type="example.com.testerapplication.sp.bean.Student_Extend"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={student1.name}"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{student2.name}"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{student3.name}"/>
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="update"/>
</LinearLayout>
</layout>
活动课
public class MainActivity extends AppCompatActivity {
private Student_XML2WAY mStudent1;
private Student_ObserField mStudent2;
private Student_Extend mStudent3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.inflate(LayoutInflater.from(this), R.layout.activity_main, null, false);
mStudent1 = new Student_XML2WAY();
mStudent1.setName("XML First");
mStudent2 = new Student_ObserField();
mStudent2.getName().set("ObserField Second");
mStudent3 = new Student_Extend();
mStudent3.setName("Extend Third");
binding.setStudent1(mStudent1);
binding.setStudent2(mStudent2);
binding.setStudent3(mStudent3);
setContentView(binding.getRoot());
binding.btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mStudent1.setName("Student1");
mStudent2.getName().set("Student2");
mStudent3.setName("Student3");
}
});
}
}
推荐答案
您的Student_XML2WAY.java
不能与2向绑定一起使用,因为它不能满足2way绑定的要求(BaseObservable
,Bindable
或像这样的东西.
Your Student_XML2WAY.java
won't work with 2-way Binding, since it does not fulfill the requirements to do so (BaseObservable
, Bindable
or something like that).
如果我将直接访问模型(如在您的Student_Extend
中),我将使用BaseObservable
.我的Activity
中将有一个Student_Extend
的实例,并将在onCreate
中设置变量:
I would use BaseObservable
if I will directly access the model, just like in your Student_Extend
. I will have an instance of Student_Extend
in my Activity
and I will set the variable in onCreate
:
Student mStudent = new Student("John Doe", 42); //
binding.setStudent(mStudent);
//later:
mStudent.setAge(37);
如果实施正确,这也会更改UI(以及模型)中的Age
.
If implemented correctly, this will also change the Age
in your UI (as well as in your model).
如果您不想直接访问模型并想使用ViewModel,请使用ObervableFields
:
If you do not want to access your model directly and want to use a ViewModel, I work with ObervableFields
:
public class Student {
private String name;
private int age;
//Corresponding setters and getters
}
public class StudentViewModel {
private ObservableField<Student> mStudentField = new ObservableField<>();
//if I have a large model class, and only want to use some fields,
//I create some getters (and setters, for the two way attributes)
//Something like this:
public int getAge() {
return mStudentField.get().getAge();
}
public void setAge(int newAge) {
return mStudentField.get().setAge(newAge);
}
}
因此,我在Activity
中创建了StudentViewModel
的实例并将其设置为绑定.伪xml看起来像这样:
So, I create an instance of StudentViewModel
in my Activity
and set it to the binding. Pseudo-xml would look like this:
<layout>
<data>
<variable name="studentViewModel"
type="locaction.of.StudentViewModel"> <!-- or do an import -->
</data>
<EditText
android:text="@={studentViewModel.age}"/>
</layout>
因此,ViewModel
方法更清晰",因为您几乎将与视图有关的所有事情都外包了.将您的BindingAdapter
,单击方法,转换器方法放在此处,并保持Activity
干净.另外,您不会直接更改模型.
对于简单的班级和项目,此方法可能会显得过大. ;)
So, the ViewModel
approach is "clearer" since you outsource almost everything that has to do with views. Put your BindingAdapter
, click methods, converter methods there and keep your Activity
clean. Also, you do not directly change your model.
This approach can be an overkill for simple classes and projects. ;)
如果您想查看使用DataBinding
和MVVM的完整示例,请查看机器人上的机器人 a>对此的解决方法.
If you want to see a full, example that uses DataBinding
and MVVM, check out Droids on roids approach on this.
这篇关于双向数据绑定(在xml中),ObservableField,BaseObservable,双向数据绑定应使用哪一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!