双向数据绑定(在xml中),ObservableField,BaseObservable,双向数据绑定应使用哪一个? [英] Two-way databinding(in xml), ObservableField, BaseObservable , which one I should use for the two-way databinding?

查看:78
本文介绍了双向数据绑定(在xml中),ObservableField,BaseObservable,双向数据绑定应使用哪一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用数据绑定已有一段时间,即使现在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绑定的要求(BaseObservableBindable或像这样的东西.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆