Two-way databinding(in xml), ObservableField, BaseObservable , which one I should use for the two-way databinding?
我已经使用了一段时间的数据绑定,即使现在它现在也不适用于JDK 8和API 24。我仍然找到一种以更简单的方式使用数据绑定的方法。但是,当我使用以下方式进行精确的双向数据绑定时(在我看来,双向数据绑定就是这里的东西(什么是双向方式?),所以发生了一些奇怪的事情。
1.双向数据绑定(在xml中)
1 | android:text="@={testStr}" |
官方文档中没有提到这一点(https://developer.android.com/topic/libraries/data-binding/index.html,此页面通常已更新,可能现在已更改)。但是可以将变量绑定到xml。
2.属性的ObservableField
此处的示例(https://developer.android.com/topic/libraries/data-binding/index.html#observablefields)
1 2 3 4 5 6 7 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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方法需要在绑定xml中使用相应的命名调用方法notifyPropertyChange()。
我的问题是,我想知道三种绑定方法的缺点和优点。当然,我知道第一个会更容易。但是有一段时间我在文档和某些网站中找到了。它在下一刻消失了。官方文档已更改,没有任何明确的声明。我仍然想知道我应该使用第一种方法,所以我必须准备更改方法2或3。
Student_XML2WAY.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?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> |
活动课
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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"); } }); } } |
您的
如果我将直接访问模型,则将使用
1 2 3 4 | Student mStudent = new Student("John Doe", 42); // binding.setStudent(mStudent); //later: mStudent.setAge(37); |
如果正确实施,这还将更改UI(以及模型)中的
如果您不想直接访问模型并想使用ViewModel,请使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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); } } |
因此,我在
1 2 3 4 5 6 7 8 | <layout> <data> <variable name="studentViewModel" type="locaction.of.StudentViewModel"> <!-- or do an import --> </data> <EditText android:text="@={studentViewModel.age}"/> </layout> |
因此,
对于简单的班级和项目,这种方法可能会显得过大。 ;)
如果要查看使用
我觉得
另外,如果您有一个自定义对象
我发现RxJava非常有用。