目录
databing的基本使用
- 开启databing
android {
........
dataBinding{
enable = true
}
}
- 修改布局文件
为布局文件添加<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>
- 实例化布局文件
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 类,实例化。传给布局并显示。
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);