【问题标题】:What is the correct way to do two-way data binding on android?在android上进行双向数据绑定的正确方法是什么?
【发布时间】:2020-08-17 02:59:23
【问题描述】:

我为 2 路数据绑定和接缝制作了一个简单的 hello world 完美运行(在 editext 上编写时,textview 会自动更新),但是像官方文档一样在线找到的所有代码都有更多的代码和复杂性,比如https://developer.android.com/topic/libraries/data-binding/two-way

这是我的代码:

public class MainActivity extends AppCompatActivity {
    public String pippo;
    public Boolean visible = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DataBindingUtil.setContentView(this, R.layout.activity_main);

    }
}



<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="pippo"
            type="String" />

        <variable
            name="visible"
            type="Boolean" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={pippo}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{pippo}"
            android:visibility="@{visible ? android.view.View.VISIBLE: android.view.View.GONE}" />

        <CheckBox
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:checked="@={visible}" />
    </LinearLayout>
</layout>

特别是文档使用这个东西,但接缝没用:

  • BaseObservable
  • @Bindable
  • 避免无限循环的代码
  • notifyPropertyChanged

那么,我的代码有什么问题或缺失?

【问题讨论】:

  • 基本上没有这些无用的东西,你实际上无法获得数据绑定的超能力。 BaseObservable 具有通知特性和回调和可绑定注释,可以对所做的更改做出反应
  • 它确实是因为属性 android:text 具有内置支持,但是假设您要创建一个功能,您必须根据编辑文本更改图标颜色为空或未赢除非您使用 BaseObservable、Bindable 和 notify 属性更改,否则无法做到这一点。双向数据绑定不起作用
  • 确定我已经给你了,只是尝试使用双向数据绑定来玩弄可见性。比如,假设你有一个布尔值 isVisible,你必须根据真假来隐藏和显示。双向数据绑定不起作用,但使用 BaseObservable、Bindable 可以使其工作。
  • 数据绑定库默认查找名为set[Attribute]get[Attribute](用于双向)的方法,如果它们存在(具有适当的输入类型),它们将用于绑定。此外,对于双向来说,需要一个获取侦听器的方法来通知它有关更改。对于内置视图,它们被实现。如果您想添加对自定义视图或自定义属性的支持,则会提供这些文档。所以如果有一些功能已经可用或如您在文档中看到的那样容易实现,它可以非常干净和简单。
  • 好问题!我们需要详细的解释。

标签: android android-databinding


【解决方案1】:

在双向数据绑定中,您需要创建从BaseObservable 扩展的类,使用@Bindable 注释getter 并在您的setter 中调用notifyPropertyChanged,如下所示:

public class Person extends BaseObservable {

    private String name;

    Person(String name) {
        this.name = name;
    }

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

}

然后将此类作为Person 类型的数据绑定布局变量传递。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="person"
            type="com.example.android......Person" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={person.name}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{person.name}" />
    </LinearLayout>
</layout>

注意:更改type属性中的类路径。

然后使用setPerson()在您的活动中设置此布局变量

public class ExampleActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DataBindingUtil.setContentView(this, R.layout.activity_example);

        ActivityExampleBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_example);

        mActivityMainBinding.setPerson(new Person(""));
    }
}

【讨论】:

  • 我的示例有效,当我在 edittext 中写入时,textview 会更新为当前的新文本。更复杂的代码有什么好处?
  • @Xan 是的,它可以工作,但对于复杂的对象它不会,你需要创建一个自定义 BaseObservable 虽然
  • 我尝试过的所有尝试都没有这些东西,这就是为什么我不明白为什么需要这样做的原因。如果没有所有这些东西,你能指定一个案例不起作用吗?
  • @Xan 例如,如果你有一些整数并且你想将它的物理值范围(比如温度范围)映射到一个微调器,你可能需要一些中间转换来匹配微调器范围,在这里,您需要在 setMyInteger() 中执行此操作。另一个示例,如果您有一个包含多个数据的 API 响应,并且您希望对它们进行双向数据绑定,那么将所有数据组合在一个 POJO BaseObservable 中会很容易
  • 用复选框和布尔可见变量编辑了我的示例,但接缝继续工作
【解决方案2】:

对我来说最简单的方法是使用@={variable} 而不是@{variable}

您可以在以下位置看到它: https://developer.android.com/topic/libraries/data-binding/two-way

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@={viewModel.name}"
    android:inputType="text" />

【讨论】:

    猜你喜欢
    • 2020-04-12
    • 1970-01-01
    • 2014-03-30
    • 2012-11-10
    • 2010-10-23
    • 2017-07-14
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    相关资源
    最近更新 更多