しばらくデータバインディングを使用しましたが、現在でもJDK 8およびAPI 24では使用できません。データバインディングをより簡単に使用する方法をまだ見つけています。しかし、次の方法を使用して正確な双方向データバインディングを実行すると(私の考えでは、双方向データバインディングはここにあります( 双方向バインディングとは) )。起こった。
1。双方向データバインディング(xml形式)
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 )
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クラスに拡張する必要があり、ゲッターメソッドには "@ Bindable"およびセッターメソッドは、メソッドnotifyPropertyChange()を、バインディングxmlの対応する名前で呼び出す必要があります。
私の質問は、3つのバインディング方法の欠点と利点を知りたいです。もちろん、私は最初の方が簡単になることを知っています。しかし、ドキュメントやウェブサイトで見つけた瞬間があります。そして次の瞬間に姿を消した。公式ドキュメントは明確な発表なしに変更されます。私はまだ最初の方法を使用する必要があるのか疑問に思うので、方法2または3を変更する準備をする必要があります。
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
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
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
<?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
は、双方向のバインディングでは機能しません。これは、そのための要件を満たさないためです(BaseObservable
、Bindable
など)。
Student_Extend
のように、モデルに直接アクセスする場合は、BaseObservable
を使用します。 Activity
にStudent_Extend
のインスタンスを作成し、onCreate
に変数を設定します。
Student mStudent = new Student("John Doe", 42); //
binding.setStudent(mStudent);
//later:
mStudent.setAge(37);
正しく実装されている場合、これにより、UI内(およびモデル内)のAge
も変更されます。
モデルに直接アクセスするのではなく、ViewModelを使用する場合は、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);
}
}
そこで、StudentViewModel
にActivity
のインスタンスを作成し、それをバインディングに設定します。 Pseudo-xmlは次のようになります。
<layout>
<data>
<variable name="studentViewModel"
type="locaction.of.StudentViewModel"> <!-- or do an import -->
</data>
<EditText
Android:text="@={studentViewModel.age}"/>
</layout>
したがって、ViewModel
アプローチは「ビュー」に関連するほとんどすべてを外部委託するため、「より明確」です。 BindingAdapter
、クリックメソッド、コンバーターメソッドをそこに配置し、Activity
をクリーンな状態に保ちます。また、モデルを直接変更することもありません。このアプローチは、単純なクラスやプロジェクトにとってはやり過ぎになる可能性があります。 ;)
DataBinding
とMVVMを使用した完全な例を確認したい場合は、これに関する Droids on roids アプローチを確認してください。
ゲッター/セッターを書く必要がないので、ObservableField
アプローチが適していると思いますOR notifyPropertyChanged
を呼び出します。
また、カスタムオブジェクト_ObservableField<Student> studentField
_があり、_Android:text="@{viewModel.studentField.name}
_を使用している場合、studentField.set(newStudent)
を呼び出すとテキストが更新されます。
RxJavaは非常に便利です。 ObservableField
は_rx.Observable
_に、またはその逆に簡単に変換できます。これにより、Rx演算子を使用できます。興味がある場合は、ここで実装を確認できます。 FieldUtils.Java