Bootstrap

android jetpack databinding的基本使用(java)

databing的基本使用

  1. 开启databing
android {
	........

    dataBinding{

        enable = true
    }
}
  1. 修改布局文件
    为布局文件添加<layout>标签。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">


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

        <TextView
            android:id="@+id/main_tv_word"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp"
            android:text="句子" />

        <TextView
            android:id="@+id/main_tv_def"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp"
            android:text="句子2" />



    </LinearLayout>
</layout>
  1. 实例化布局文件
    ActivityMainBinding activityMainBinding;

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

        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    }
  1. 向布局文件传递数据

创建一个Sentence 类,实例化。传给布局并显示。

public class Sentence {

    private String sentence;


    private String sentenceCH;


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

    <data>
        <variable
            name="sentence"
            type="cn.jn.mytest.entity.Sentence" />
    </data>

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

        <TextView
            android:id="@+id/main_tv_word"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp"
            android:text="@{sentence.sentence}" />

        <TextView
            android:id="@+id/main_tv_def"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp"
            android:text="@{sentence.sentenceCH}" />


    </LinearLayout>
</layout>
    ActivityMainBinding activityMainBinding;

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

        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        Sentence sentence = new Sentence();
        sentence.setSentence("Hello");
        sentence.setSentenceCH("你好");
        activityMainBinding.setSentence(sentence);

    }

在这里插入图片描述 5. 在布局中引用静态类
在sentence类中添加属性collect ,collect 等于1表示已收藏,0表示收藏。
建立工具类CollectUtil

public class CollectUtil {
    public static String getCollectString(int collect) {

        if (collect == 1) {

            return "已收藏";
        } else {

            return "未收藏";
        }
    }
}

通过<import>导入到布局文件中

    <data>

        <variable
            name="sentence"
            type="cn.jn.mytest.entity.Sentence" />

        <import type="cn.jn.mytest.util.CollectUtil" />
    </data>

调用CollectUtil

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

    <data>

        <variable
            name="sentence"
            type="cn.jn.mytest.entity.Sentence" />

        <import type="cn.jn.mytest.util.CollectUtil" />
    </data>

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

        <TextView
            android:id="@+id/main_tv_word"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp"
            android:text="@{sentence.sentence}" />

        <TextView
            android:id="@+id/main_tv_def"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp"
            android:text="@{sentence.sentenceCH}" />


        <TextView
            android:id="@+id/main_tv_collect"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp"
            android:text="@{CollectUtil.getCollectString(sentence.collect)}" />


    </LinearLayout>
</layout>

在这里插入图片描述

二级页面的绑定

当我们在activity或者fragment的布局中,使用<include>引入的布局叫二级页面。

一级页面


    <data>

        <variable
            name="sentence"
            type="cn.jn.mytest.entity.Sentence" />

        <import type="cn.jn.mytest.util.CollectUtil" />
    </data>
   <include
            layout="@layout/toolbar"
            app:sentence="@{sentence}" />

二级页面需要创建个相同名字的变量

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

    <data>

        <variable
            name="sentence"
            type="cn.jn.mytest.entity.Sentence" />
    </data>

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

        <TextView
            android:id="@+id/toolbar_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{sentence.sentence}" />

    </LinearLayout>
</layout>

自定义BindingAdapter

bindingadapter中的方法都是静态方法,需要添加@BindingAdapter,第一个参数为控件本身,第二个参数是布局文件传过来参数,

public class TextBindingAdapter {
    @BindingAdapter("collect")
    public static void setCollect(TextView textView, int collect) {

        if (collect == 1) {

            textView.setTextColor(Color.GREEN);
            textView.setText("已收藏");
        } else {

            textView.setTextColor(Color.GRAY);
            textView.setText("未收藏");
        }
    }
}	
        <TextView
            android:id="@+id/main_tv_collect"
            collect="@{sentence.collect}"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp" />

在这里插入图片描述

自定义BinddingAdapter的可选旧值

oldcollect是旧值,newCollect是新值。可以用来防止重复调用。

    @BindingAdapter("collect")
    public static void setCollect(TextView textView, int oldCollect, int newCollect) {


        if (oldCollect == newCollect) {

            return;
        }

        if (newCollect == 1) {

            textView.setTextColor(Color.GREEN);
            textView.setText("已收藏");
        } else {

            textView.setTextColor(Color.GRAY);
            textView.setText("未收藏");
        }
    }
        <TextView
            android:id="@+id/main_tv_collect"
            collect="@{sentence.collect}"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="13dp" />

双向绑定

前面的所涉及的绑定是单向绑定,根据字段来更新控件的内容。
通过交互修改edittext 的内容,使得对应的字段自动更新。
实现

public class NameModel {

    public String name;
}

创建一个双向绑定的业务逻辑类,继承BaseObservable 。给getter添加@Bindable,对字段进行双向绑定。setter方法会在用户编辑edittext时自动调用,内容更新后,会调用notifyPropertyChanged方法,通知观察者,数据已更新,更新ui。

public class NameViewModel extends BaseObservable {

    private NameModel nameModel;


    public NameViewModel() {

        nameModel = new NameModel();
        nameModel.name = "zhang san";
    }


    @Bindable
    public String getName() {


        return nameModel.name;
    }

    public void setName(String name) {

            nameModel.name = name;
            notifyPropertyChanged(BR.name);
    }
}

在布局中的使用,@{}变乘@={}。
main_tt_name2是textview,这个为了调用notifyPropertyChanged后,能够直观的看到内容变化。

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="nameViewModel"
            type="cn.jn.mytest.observable.NameViewModel" />
    </data>

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


        <EditText
            android:id="@+id/main_et_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={nameViewModel.name}" />

        <TextView
            android:id="@+id/main_tt_name2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{nameViewModel.name}" />

    </LinearLayout>
</layout>

效果图
在这里插入图片描述

使用ObservableField来进行双向绑定

public class NameViewModel2 {


    private ObservableField<NameModel> nameModelObservableField;


    public NameViewModel2() {

        NameModel nameModel = new NameModel();
        nameModel.name = "zhang san";

        nameModelObservableField = new ObservableField<>();
        nameModelObservableField.set(nameModel);

    }


    public String getName() {

        return nameModelObservableField.get().name;
    }

    public void setName(String name) {

        nameModelObservableField.get().name = name;
    }

}

布局,main_tt_name2在这里不起作用,所以添加了button来获取值。

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="nameViewModel"
            type="cn.jn.mytest.observable.NameViewModel2" />
    </data>

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


        <EditText
            android:id="@+id/main_et_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={nameViewModel.name}" />

        <TextView
            android:id="@+id/main_tt_name2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{nameViewModel.name}" />

        <Button
            android:id="@+id/main_but_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="获取名字" />

    </LinearLayout>
</layout>

效果图
在这里插入图片描述
在这里插入图片描述

在recycleview中使用databinding

item的布局文件

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="sentence"
            type="cn.jn.mytest.entity.Sentence" />
    </data>

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

        <TextView
            android:id="@+id/sentence_tv_sentence"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{sentence.sentence}" />

        <TextView
            android:id="@+id/sentence_tv_sentence_ch"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{sentence.sentenceCH}" />


    </LinearLayout>
</layout>

适配器

public class SentenceAdapter extends RecyclerView.Adapter<SentenceAdapter.SentenceViewHolder> {

    private List<Sentence> sentenceList;


    public SentenceAdapter(List<Sentence> sentenceList) {
        this.sentenceList = sentenceList;
    }

    @NonNull
    @Override
    public SentenceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        ItemSentenceBinding itemSentenceBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.item_sentence, parent, false);
        return new SentenceViewHolder(itemSentenceBinding);
    }

    @Override
    public void onBindViewHolder(@NonNull SentenceViewHolder holder, int position) {

        Sentence sentence = sentenceList.get(position);
        holder.itemSentenceBinding.setSentence(sentence);
    }

    @Override
    public int getItemCount() {
        return sentenceList.size();
    }

    public static class SentenceViewHolder extends RecyclerView.ViewHolder {

        ItemSentenceBinding itemSentenceBinding;

        public SentenceViewHolder(@NonNull ItemSentenceBinding itemView) {
            super(itemView.getRoot());
            this.itemSentenceBinding = itemView;
        }
    }
}

使用

        List<Sentence> sentenceList = new ArrayList<>();
        sentenceList.add(new Sentence("hello", "你好", 0));
        sentenceList.add(new Sentence("His trousers are the same as mine.", "他的裤子和我的一样。", 0));
        sentenceList.add(new Sentence("Let him not stand in the rain.", "让他不要站在雨中。", 0));

        RecyclerView main_rv_list = findViewById(R.id.main_rv_list);

        main_rv_list.setLayoutManager(new LinearLayoutManager(this));
        SentenceAdapter sentenceAdapter = new SentenceAdapter(sentenceList);
        main_rv_list.setAdapter(sentenceAdapter);
;