【Android】DataBinding 最全利用解析

打印 上一主题 下一主题

主题 537|帖子 537|积分 1611


一、DataBinding 概述



DataBinding 是谷歌官方在2015谷歌I/O大会发布的一个数据绑定框架,是 MVVM 模式在 Android 上的一种实现,用于低落布局和逻辑的耦合性,使代码逻辑更加清楚。DataBinding 可以或许省去我们一直以来的 findViewById() 步骤,大量淘汰 Activity 内的代码,DataBinding 也是Android Jetpack中非常重要的一部门。
二、基本用法


2.1 利用入门



DataBinding 在android工程中默认是关闭的,需要在build.gradle文件中添加一下配置开启DataBinding
   android {
        ...
        dataBinding {
            enabled = true
        }
    }
   
找到需要开启DataBinding 的Activity对应的布局文件,将鼠标放到布局文件的第一行选择Convert to data binding layout主动转换。即可将布局文件改造成DataBinding 格式。
  



将Activity对应的布局文件主动天生以布局文件名字开头Binding结尾的Java类,如下代码所示
  1. public class MainActivity extends AppCompatActivity {
  2.     ActivityMainBinding activityMainBinding;
  3.     @Override
  4.     protected void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
  7.         
  8.     }
  9. }
复制代码
  

RecyclerView中利用DataBinding
  
   
  1. public class  MyAdatper extends RecyclerView.Adapter<MyViewHolder>{
  2.         @NonNull
  3.         @Override
  4.         public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
  5.             ChatitemBinding chatitemBinding =
  6.                     DataBindingUtil.inflate(LayoutInflater.from(MainActivity.this),R.layout.chatitem,parent,false);
  7.             MyViewHolder myViewHolder = new MyViewHolder(chatitemBinding.getRoot());
  8.             myViewHolder.chatitemBinding = chatitemBinding;
  9.             return myViewHolder;
  10.         }
  11.         @Override
  12.         public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
  13.             holder.chatitemBinding.setItem(chatlist.get(position));
  14.         }
  15.         @Override
  16.         public int getItemCount() {
  17.             return chatlist.size();
  18.         }
  19.     }
  20.     public class MyViewHolder extends RecyclerView.ViewHolder{
  21.         ChatitemBinding chatitemBinding;
  22.         public MyViewHolder(@NonNull View itemView) {
  23.             super(itemView);
  24.         }
  25.     }
复制代码
  
Fragment 中利用DataBinding
  1. public class FirstFragment extends Fragment {
  2.     private FragmentFirstBinding binding;
  3.     @Override
  4.     public View onCreateView(
  5.             LayoutInflater inflater, ViewGroup container,
  6.             Bundle savedInstanceState    ) {
  7.         binding = FragmentFirstBinding.inflate(inflater, container, false);
  8.         return binding.getRoot();
  9.     }
  10. }
复制代码
  
2.2 布局和绑定表达式


  
要想实现数据绑定,需要在布局文件的data节点中界说variable节点,节点的name属性代表变量名字,type属性代表变量范例
在控件的属性中通过@{}表达式把声明出来的数据对象设置给对应的 控件属性,在表达式语言中还可以利用以下运算符和关键字:


  算术运算符+ - / * %
字符勾通接运算符+
逻辑运算符&& ||
instanceof
三元运算符?:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     xmlns:tools="http://schemas.android.com/tools">
  5.     <data>
  6.         <variable
  7.             name="content"
  8.             type="String" />
  9.         <variable
  10.             name="enabled"
  11.             type="boolean" />
  12.         <variable
  13.             name="person"
  14.             type="com.example.databinding.Person" />
  15.     </data>
  16.     <androidx.constraintlayout.widget.ConstraintLayout
  17.         android:layout_width="match_parent"
  18.         android:layout_height="match_parent"
  19.         tools:context=".MainActivity">
  20.         <TextView
  21.             android:id="@+id/textView"
  22.             android:layout_width="wrap_content"
  23.             android:layout_height="wrap_content"
  24.             android:text='@{enabled ? "真" :"假"}'
  25.             app:layout_constraintBottom_toBottomOf="parent"
  26.             app:layout_constraintEnd_toEndOf="parent"
  27.             app:layout_constraintStart_toStartOf="parent"
  28.             app:layout_constraintTop_toTopOf="parent" />
  29.         <TextView
  30.             android:id="@+id/textView2"
  31.             android:layout_width="wrap_content"
  32.             android:layout_height="wrap_content"
  33.             android:layout_marginTop="13dp"
  34.             android:layout_marginEnd="20dp"
  35.             android:text="@{person.name}"
  36.             app:layout_constraintEnd_toEndOf="@+id/textView"
  37.             app:layout_constraintTop_toBottomOf="@+id/textView" />
  38.         <TextView
  39.             android:id="@+id/textView3"
  40.             android:layout_width="wrap_content"
  41.             android:layout_height="wrap_content"
  42.             android:layout_marginBottom="114dp"
  43.             android:text='@{"test"+person.age}'
  44.             app:layout_constraintBottom_toTopOf="@+id/textView"
  45.             app:layout_constraintEnd_toEndOf="parent"
  46.             app:layout_constraintStart_toStartOf="parent" />
  47.         <TextView
  48.             android:id="@+id/textView4"
  49.             android:layout_width="wrap_content"
  50.             android:layout_height="wrap_content"
  51.             android:layout_marginBottom="62dp"
  52.             android:text="@{content}"
  53.             app:layout_constraintBottom_toTopOf="@+id/textView3"
  54.             app:layout_constraintEnd_toEndOf="parent"
  55.             app:layout_constraintStart_toStartOf="parent" />
  56.     </androidx.constraintlayout.widget.ConstraintLayout>
  57. </layout>
复制代码
  1. 在activity中使用activityMainBinding对象的setContentView方法来设置绑定
  2. public class MainActivity extends AppCompatActivity {
  3.     ActivityMainBinding activityMainBinding;
  4.     @Override
  5.     protected void onCreate(Bundle savedInstanceState) {
  6.         super.onCreate(savedInstanceState);
  7.         activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
  8.         Person person = new Person();
  9.         person.age = 20;
  10.         person.name = "test";
  11.         String content = "content";
  12.         boolean enable = false;
  13.         activityMainBinding.setPerson(person);
  14.         activityMainBinding.setContent(content);
  15.         activityMainBinding.setEnabled(enable);
  16.     }
  17. }
复制代码
  
2.3 事件绑定


  
DataBinding不但可以将值绑定到控件上,还可以将事件绑定到控件上。
首先在activity中界说一个类,在该类中界说一个参数为View的方法,并将该类用activityMainBinding对象的setContentView方法来设置绑定。
  1. public class MainActivity extends AppCompatActivity {
  2.     ActivityMainBinding activityMainBinding;
  3.     @Override
  4.     protected void onCreate(Bundle savedInstanceState) {
  5.         super.onCreate(savedInstanceState);
  6.         activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
  7.          activityMainBinding.setPresenter(new Presenter());
  8.     }
  9.     public  class Presenter{
  10.         public void onClick(View view){
  11.             Log.i("Presenter","onClick");
  12.         }
  13.     }
  14. }
复制代码

 
  1. 在布局文件中,data节点设置该点击事件对象,然后在控件的android:onClick="@{presenter.onClick}"属性中设置绑定即可。
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  4.     xmlns:app="http://schemas.android.com/apk/res-auto"
  5.     xmlns:tools="http://schemas.android.com/tools">
  6.     <data>
  7.          <variable
  8.             name="presenter"
  9.             type="com.example.databinding.MainActivity.Presenter" />
  10.     </data>
  11.     <androidx.constraintlayout.widget.ConstraintLayout
  12.         android:layout_width="match_parent"
  13.         android:layout_height="match_parent"
  14.         tools:context=".MainActivity">
  15.          <Button
  16.             android:id="@+id/button"
  17.             android:layout_width="wrap_content"
  18.             android:layout_height="wrap_content"
  19.             android:layout_marginEnd="147dp"
  20.             android:layout_marginBottom="75dp"
  21.             android:text="Button"
  22.             android:onClick="@{presenter.onClick}"
  23.             app:layout_constraintBottom_toBottomOf="parent"
  24.             app:layout_constraintEnd_toEndOf="parent" />
  25.     </androidx.constraintlayout.widget.ConstraintLayout>
  26. </layout>
复制代码

  1. 带参数的事件绑定
  2. 将点击类的中定义的方法onClick参数改成需要点击回传的参数,在点击事件控件中设置android:onClick="@{()->presenter.onClick(person)}"即可将布局文件的变量中通过点击事件回传。
  3. public  class Presenter{
  4.     public void onClick(Person person){
  5.         Log.i("Presenter","onClick" + person.name);
  6.     }
  7. }
复制代码

 
  1. <Button
  2.     android:id="@+id/button"
  3.     android:layout_width="wrap_content"
  4.     android:layout_height="wrap_content"
  5.     android:layout_marginEnd="147dp"
  6.     android:layout_marginBottom="75dp"
  7.     android:text="Button"
  8.     android:onClick="@{()->presenter.onClick(person)}"
  9.     app:layout_constraintBottom_toBottomOf="parent"
  10.     app:layout_constraintEnd_toEndOf="parent" />
复制代码

2.4 单向绑定


   
上面的对象绑定,当对象的值改变并不会引起页面控件的主动更新,要想实现数据厘革后视图也跟着主动厘革可以利用以下两种方法:
方法1:继承BaseObservable类,并将对象的属性添加set和get方法
  1. public class Person extends BaseObservable {
  2.     public int age;
  3.     public String name;
  4.     public int getAge() {
  5.         return age;
  6.     }
  7.     public void setAge(int age) {
  8.         this.age = age;
  9.     }
  10.     public String getName() {
  11.         return name;
  12.     }
  13.     public void setName(String name) {
  14.         this.name = name;
  15.         notifyChange();
  16.     }
  17. }
复制代码
  
当对象给相应的属性赋值后,页面控件绑定的值即可实现主动革新
  1. public  class Presenter{
  2.     public void onClick(Person person){
  3.         person.setName( "new test");
  4.         person.setAge( 30);
  5.         Log.i("Presenter","onClick" + person.name);
  6.     }
  7. }
复制代码

 
  1. 如果只想属性的部分值更新,在该属性的get方法上添加 @Bindable即可
  2. import androidx.databinding.BaseObservable;
  3. import androidx.databinding.Bindable;
  4. public class Person extends BaseObservable {
  5.     public int age;
  6.     public String name;
  7.     @Bindable
  8.     public int getAge() {
  9.         return age;
  10.     }
  11.     public void setAge(int age) {
  12.         this.age = age;
  13.     }
  14.     @Bindable
  15.     public String getName() {
  16.         return name;
  17.     }
  18.     public void setName(String name) {
  19.         this.name = name;
  20.         notifyPropertyChanged(BR.name);
  21.     }
  22. }
复制代码
  
方法2:
  该类的属性用ObservableField封装同样的也可以实现单向绑定
  public class Person   {
    public ObservableField<Integer> age = new ObservableField<>();
    public ObservableField<String> name = new ObservableField<>();
}

也可以用一下范例
  BaseObservable,
ObservableBoolean,
ObservableByte,
ObservableChar,
ObservableDouble,
ObservableField,
ObservableFloat,
ObservableInt,
ObservableLong,
ObservableParcelable,
ObservableShort,
该对象的属性会自带set和get方法,调用set方法即可实现页面控件绑定的数据主动革新
   public  class Presenter{
        public void onClick(Person person){
            person.name.set( "new test");
            person.age.set( 30);
            Log.i("resenter","onClick" + person.name);
            content.set("new content");
        }
    }
  
2.5 双向绑定


  
对于输入控件,利用@={}表达式即可实现页面和绑定的值双向主动革新
    <EditText
    android:id="@+id/editTextTextPersonName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="85dp"
    android:layout_marginBottom="7dp"
    android:ems="10"
    android:inputType="textPersonName"
    android:text="@={content}"
    app:layout_constraintBottom_toBottomOf="@+id/textView3"
    app:layout_constraintEnd_toEndOf="parent" />
  
完整代码如下所示
  1. public class MainActivity extends AppCompatActivity {
  2.     ActivityMainBinding activityMainBinding;
  3.     ObservableField<String> content;
  4.     @Override
  5.     protected void onCreate(Bundle savedInstanceState) {
  6.         super.onCreate(savedInstanceState);
  7.         activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
  8.         content = new ObservableField<>("content ");
  9.         activityMainBinding.setContent(content);
  10.     }
  11. }
  12. <?xml version="1.0" encoding="utf-8"?>
  13. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  14.     xmlns:app="http://schemas.android.com/apk/res-auto"
  15.     xmlns:tools="http://schemas.android.com/tools">
  16.     <data>
  17.         <variable
  18.             name="content"
  19.             type="androidx.databinding.ObservableField&lt;String&gt;" />
  20.     </data>
  21.     <androidx.constraintlayout.widget.ConstraintLayout
  22.         android:layout_width="match_parent"
  23.         android:layout_height="match_parent"
  24.         tools:context=".MainActivity">
  25.         <TextView
  26.             android:id="@+id/textView"
  27.             android:layout_width="wrap_content"
  28.             android:layout_height="wrap_content"
  29.             android:text='@{content}'
  30.             app:layout_constraintBottom_toBottomOf="parent"
  31.             app:layout_constraintEnd_toEndOf="parent"
  32.             app:layout_constraintStart_toStartOf="parent"
  33.             app:layout_constraintTop_toTopOf="parent" />
  34.         <EditText
  35.             android:id="@+id/editTextTextPersonName"
  36.             android:layout_width="wrap_content"
  37.             android:layout_height="wrap_content"
  38.             android:layout_marginTop="44dp"
  39.             android:layout_marginEnd="84dp"
  40.             android:ems="10"
  41.             android:inputType="textPersonName"
  42.             android:text="@={content}"
  43.             app:layout_constraintEnd_toEndOf="parent"
  44.             app:layout_constraintTop_toBottomOf="@+id/textView" />
  45.     </androidx.constraintlayout.widget.ConstraintLayout>
  46. </layout>
复制代码

三、高级用法



BindingAdapter
DataBinding支持在平凡方法上添加@注解来添加自界说控件属性,该方法需满足以下条件:
修饰方法, 要求方法必须public static
方法参数第一个要求必须是View
方法名不作要求

    @BindingAdapter("imageurl")
    public static void bindImageUrl(ImageView view,String url){
        Glide.with(view)
                .load(url)
                .into(view);
    }


利用方法如下:
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="150dp"
            android:layout_height="150dp"
            app:imageurl="@{item.head}"
     />

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊落一身雪

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表