dataBinding是google推出來的一個(gè)mvvm的框架输吏,出來有一段時(shí)間了权旷,由于之前的項(xiàng)目都是用mvc或者mvp的模式開發(fā),沒有使用mvvm模式進(jìn)行開發(fā)贯溅,這次公司項(xiàng)目用的是jetpack框架拄氯,涉及到ViewModel、dataBinding等它浅,所以就利用些空閑時(shí)間了解和學(xué)習(xí)下dataBinding的一些使用译柏。
準(zhǔn)備工作:
要使用dataBinding的話,首先要在app model 下build.gradle文件的android節(jié)點(diǎn)下添加
dataBinding{
enabled=true
}
如:
數(shù)據(jù)綁定
在xml布局中使用dataBinding時(shí)罚缕,要將xml布局文件的節(jié)點(diǎn)進(jìn)行修改艇纺,如:
<?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>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</layout>
將layout節(jié)點(diǎn)放最外面怎静,接著是data節(jié)點(diǎn)邮弹,在data節(jié)點(diǎn)中可以新增variable節(jié)點(diǎn),在data節(jié)點(diǎn)下面可以寫之前的布局節(jié)點(diǎn)蚓聘;
<?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="employee"
type="com.lsm.databindingtest.Employee" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/first_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="@{employee.firstName}" />
<TextView
android:id="@+id/last_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:text="@{employee.lastName}" />
</LinearLayout>
</layout>
variable節(jié)點(diǎn)中name是type的一個(gè)名稱腌乡,type是對應(yīng)model類的包名路徑,通過@{}的方式對TextView進(jìn)行賦值夜牡;在activity文件中通過DataBindingUtil進(jìn)行引用与纽;
public class SimpleActivity extends AppCompatActivity {
private ActivitySimpleBinding binding;
private Employee employee = new Employee("Zhai", "Mark");
private Worker worker = new Worker("1111", "2222");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_simple);
//通過直接賦值
// binding.firstName.setText(employee.getFirstName());
// binding.lastName.setText(employee.getLastName());
// binding.setEmployee(employee);
binding.setVariable(BR.employee, employee);
}
}
ActivitySimpleBinding命名:布局文件名稱(第一字母大寫侣签,遇到,去掉并將首字母大寫)+Binding;
這里賦值有三種方式:
1急迂、通過ActivitySimpleBinding.控件id影所,直接賦值;
如:binding.firstName.setText(employee.getFirstName());
2、ActivitySimpleBinding調(diào)用set方法;
如:binding.setEmployee(employee);
3僚碎、ActivitySimpleBinding調(diào)用setVariable方法;
binding.setVariable(BR.employee, employee);
事件綁定
事件可以通過方法或者監(jiān)聽器的形式來實(shí)現(xiàn)猴娩;
在對應(yīng)的activity中聲明一個(gè)事件的內(nèi)部類,在內(nèi)部類中定義對應(yīng)的事件方法勺阐,在xml布局中通過新增variable節(jié)點(diǎn)卷中,對它的name和type屬性進(jìn)行設(shè)置,也是用過@{}的方式綁定事件渊抽;
<?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="eventlistener"
type="com.lsm.databindingtest.SimpleActivity.EventListener" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:onClick="@{eventlistener.clickFirst}"
android:text="點(diǎn)擊(方法)" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:onClick="@{(view)->eventlistener.btnClick(view)}"
android:text="點(diǎn)擊(監(jiān)聽器)" />
<Button
android:id="@+id/longc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:onLongClick="@{eventlistener::onLongClick}"
android:text="長按" />
</LinearLayout>
</layout>
public class SimpleActivity extends AppCompatActivity {
private ActivitySimpleBinding binding;
private Employee employee = new Employee("Zhai", "Mark");
private Worker worker = new Worker("1111", "2222");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_simple);
binding.setEventlistener(new EventListener());
}
public class EventListener {
public void clickFirst(View view) {
worker.setFirstName("55555");
worker.setLastName("7777777");
Toast.makeText(SimpleActivity.this, "點(diǎn)擊了并刷新worker對象的值", Toast.LENGTH_LONG).show();
}
public void btnClick(View view){
Toast.makeText(SimpleActivity.this, "監(jiān)聽器方式", Toast.LENGTH_LONG).show();
}
public boolean onLongClick(View view) {
Toast.makeText(SimpleActivity.this, "長按了", Toast.LENGTH_LONG).show();
return false;
}
}
}
activity中通過setEventlistener方法傳入EventListener對象蟆豫,setEventlistener方法是自動(dòng)生成的就可以了;在定義事件方法名稱時(shí)需要注意:方法的名稱可以和之前寫法不一樣懒闷,但是方法名稱的參數(shù)要和之前的寫法一樣十减,不然會(huì)報(bào)錯(cuò),比如:clickFirst(View view)必須要有view參數(shù)愤估,如果沒有會(huì)報(bào)錯(cuò)
BaseObservable
BaseObservable在數(shù)據(jù)發(fā)生改變時(shí)通知xml布局試圖進(jìn)行刷新
public class Worker extends BaseObservable {
private String mLastName;
private String mFirstName;
private boolean mIsFired=false;
public Worker(String mLastName, String mFirstName) {
this.mLastName = mLastName;
this.mFirstName = mFirstName;
}
@Bindable
public String getLastName() {
return mLastName;
}
public void setLastName(String mLastName) {
this.mLastName = mLastName;
notifyPropertyChanged(BR.lastName);
}
@Bindable
public String getFirstName() {
return mFirstName;
}
public void setFirstName(String mFirstName) {
this.mFirstName = mFirstName;
notifyPropertyChanged(BR.firstName);
}
@Bindable
public boolean getFired() {
return mIsFired;
}
public void setFired(boolean mIsFired) {
this.mIsFired = mIsFired;
//刷新所有有關(guān)的ui
// notifyChange();
}
}
定義一個(gè)model類繼承自BaseObservable嫉称,在get方法上添加@Bindable注解,在set方法中notifyPropertyChanged(BR.lastName)方法更新指定的視圖灵疮,通過notifyChange();方法更新所有的視圖织阅,即使數(shù)據(jù)沒有更新也會(huì)重新刷新視圖;
<?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="eventlistener"
type="com.lsm.databindingtest.SimpleActivity.EventListener" />
<variable
name="worker"
type="com.lsm.databindingtest.Worker"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:onClick="@{eventlistener.clickFirst}"
android:text="點(diǎn)擊(方法)" />
<include
bind:worker="@{worker}"
layout="@layout/name" />
</LinearLayout>
</layout>
name.xml
<?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="worker"
type="com.lsm.databindingtest.Worker"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:text="@{worker.firstName}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:text="@{worker.lastName}"/>
</LinearLayout>
</layout>
點(diǎn)擊調(diào)用clickFirst方法時(shí)改變inclue 中name.xml中的視圖震捣;
public class SimpleActivity extends AppCompatActivity {
private ActivitySimpleBinding binding;
private Worker worker = new Worker("1111", "2222");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_simple);
binding.setEventlistener(new EventListener());
binding.setWorker(worker);
}
public class EventListener {
public void clickFirst(View view) {
worker.setFirstName("55555");
worker.setLastName("7777777");
Toast.makeText(SimpleActivity.this, "點(diǎn)擊了并刷新worker對象的值", Toast.LENGTH_LONG).show();
}
}
}
在觸發(fā)點(diǎn)擊事件荔棉,重新對model進(jìn)行賦值后,并沒有做其他動(dòng)作蒿赢,視圖就更新了润樱;
include
在BaseObservable視圖更新中其實(shí)就提到了include的使用了;
<?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="worker"
type="com.lsm.databindingtest.Worker"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
bind:worker="@{worker}"
layout="@layout/name" />
</LinearLayout>
</layout>
name.xml
<?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="worker"
type="com.lsm.databindingtest.Worker"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:text="@{worker.firstName}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"
android:text="@{worker.lastName}"/>
</LinearLayout>
</layout>
activity中的邏輯和上面都差不多羡棵,這里就不說了壹若;
ViewStub
有時(shí)候在項(xiàng)目開發(fā)中會(huì)使用ViewStub進(jìn)行加載視圖,看看在dataBinding中如何使用ViewStub皂冰;
<?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>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub
android:id="@+id/view_stub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout="@layout/viewstub"/>
</LinearLayout>
</layout>
viewstub.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher_round"/>
</LinearLayout>
和之前的使用一樣沒有區(qū)別店展;
RecyclerView
在開發(fā)過程中列表(RecyclerView,ListView,GridView等)的使用是比較頻繁的,所有就來看看RecyclerView在dataBinding中是如何綁定數(shù)據(jù)的秃流;
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="controllrecyclerview"
type="com.lsm.databindingtest.RecyclerViewActivity.ControllRecyclerView"/>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="增加"
tools:ignore="MissingConstraints"
android:onClick="@{controllrecyclerview.addItem}"/>
<Button
android:id="@+id/btn_remove"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="刪除"
tools:ignore="MissingConstraints"
app:layout_constraintTop_toBottomOf="@+id/btn_add"
android:onClick="@{controllrecyclerview::removeItem}"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints"
app:layout_constraintTop_toBottomOf="@+id/btn_remove">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
</layout>
布局中和之前的寫法一樣赂蕴,看看它adapter的寫法有什么不同;
public class BindingViewHolder<T extends ViewDataBinding> extends RecyclerView.ViewHolder {
private T mBinding;
public BindingViewHolder(@NonNull T binding) {
super(binding.getRoot());
mBinding = binding;
}
public T getBinding() {
return mBinding;
}
}
這了ViewHolder弄一個(gè)單獨(dú)的類舶胀,沒有將其弄成adapter的內(nèi)部類了概说,實(shí)例化的時(shí)和以前不同的時(shí)傳入dataBinding對象而不是View對象碧注,然后通過getRoot方法去獲取View對象;
public class EmployeeAdapter extends RecyclerView.Adapter<BindingViewHolder> {
private LayoutInflater mLayoutInflater;
private OnItemClickListener mListener;
private List<Worker> mWorkList;
public interface OnItemClickListener {
void onItemClickListener(Worker worker);
}
public EmployeeAdapter(Context context) {
this.mLayoutInflater = LayoutInflater.from(context);
this.mWorkList = new ArrayList<>();
}
@NonNull
@Override
public BindingViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
ViewDataBinding binding = DataBindingUtil.inflate(mLayoutInflater, R.layout.item_work_on, viewGroup, false);
return new BindingViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull BindingViewHolder bindingViewHolder, int i) {
final Worker item = mWorkList.get(i);
ViewDataBinding binding = bindingViewHolder.getBinding();
binding.setVariable(BR.item, item);
binding.executePendingBindings();
bindingViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onItemClickListener(item);
}
}
});
}
@Override
public int getItemCount() {
return mWorkList.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mListener = listener;
}
public void addAll(List<Worker> workers) {
mWorkList.addAll(workers);
}
Random mRandom = new Random(System.currentTimeMillis());
public void add(Worker worker) {
int position = mRandom.nextInt(mWorkList.size() +1);
mWorkList.add(position,worker);
notifyItemInserted(mWorkList.size());
}
public void remove() {
if (mWorkList.size() == 0) {
return;
}
int position = mRandom.nextInt(mWorkList.size());
mWorkList.remove(position);
notifyItemRemoved(position);
}
}
在onCreateViewHolder方法中通過DataBindingUtil.inflate加載視圖布局糖赔,并創(chuàng)建ViewDataBinding實(shí)例對象萍丐;onBindViewHolder方法中就不用像之前那樣通過獲取控件,然后對控件進(jìn)行賦值放典,直接通過ViewHolder獲取到對應(yīng)的ViewDataBinding碉纺,然后調(diào)用setVariable對視圖進(jìn)行賦值,點(diǎn)擊事件這些也可以按照之前的方式實(shí)現(xiàn)刻撒;
item_work_on.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="item"
type="com.lsm.databindingtest.Worker"/>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:id="@+id/id_first_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints"
android:text="@{item.firstName}"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints"
android:text="@{item.lastName}"
app:layout_constraintBottom_toTopOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/id_first_name"
android:layout_marginLeft="30dp"/>
</android.support.constraint.ConstraintLayout>
</layout>
public class RecyclerViewActivity extends AppCompatActivity {
private ActivityRecyclerviewBinding binding;
private EmployeeAdapter adapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_recyclerview);
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new EmployeeAdapter(this);
binding.recyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(new EmployeeAdapter.OnItemClickListener() {
@Override
public void onItemClickListener(Worker worker) {
Toast.makeText(RecyclerViewActivity.this, worker.getFirstName() + "--" + worker.getLastName(), Toast.LENGTH_LONG).show();
}
});
binding.setControllrecyclerview(new ControllRecyclerView());
List<Worker> demoList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Worker worker = new Worker("Zhai", "Mark");
demoList.add(worker);
}
adapter.addAll(demoList);
}
public class ControllRecyclerView {
public void addItem(View view) {
Worker worker = new Worker("1111", "11111");
adapter.add(worker);
}
public void removeItem(View view) {
adapter.remove();
}
}
}
activity中直接通過dataBinding獲取RecyclerView實(shí)例骨田,然后設(shè)置LayoutMananger和adapter;這樣就實(shí)現(xiàn)了列表數(shù)據(jù)的綁定声怔,對于ListView和GridView列表數(shù)據(jù)的綁定差不多态贤;
@BindingAdapter自定義屬性
要將后臺返回的url圖片鏈接通過ImageView顯示在界面上,需要通過第三方圖片加載庫將其加載顯示出來醋火,在dataBinding中xml布局中ImageView并不能通過@{}的方式加載url鏈接悠汽,那怎么來實(shí)現(xiàn)圖片加載呢?通過@BindingAdapter自定義屬性的方式可以實(shí)現(xiàn)芥驳;
public class DemoBindingAdapter {
@BindingAdapter({"app:imageUrl","app:placeholder"})
public static void loadImageFromUrl(ImageView view, String url, Drawable drawable){
Glide.with(view.getContext())
.load(url)
.placeholder(drawable)
.into(view);
}
}
定義一個(gè)loadImageFromUrl的靜態(tài)方法柿冲,并給方法添加@BindingAdapter注解,在注解中聲明一個(gè)imageUrl和placeholder兆旬,在xml中給imageUrl和placeholder進(jìn)行賦值假抄;
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="employee"
type="com.lsm.databindingtest.Employee" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_a"
android:layout_width="150dp"
android:layout_height="150dp"
app:imageUrl="@{employee.avatar}"
app:placeholder="@{@drawable/default_avatar}"
tools:ignore="MissingConstraints" />
<ImageView
android:id="@+id/iv_b"
android:layout_width="150dp"
android:layout_height="150dp"
app:imageUrl="@{employee.avatar}"
app:layout_constraintTop_toBottomOf="@+id/iv_a"
app:placeholder="@{@drawable/default_avatar}"
tools:ignore="MissingConstraints" />
</android.support.constraint.ConstraintLayout>
</layout>
通過app:imageUrl和app:placeholder進(jìn)行引用;
public class ExpressionActivity extends AppCompatActivity {
private ActivityExpressionBinding binding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding= DataBindingUtil.setContentView(this,R.layout.activity_expression);
Employee employee=new Employee("111","3333");
employee.setAvatar("http://img.tupianzj.com/uploads/allimg/160728/9-160HP91408.jpg");
binding.setEmployee(employee);
}
}
雙向綁定
雙向綁定的意思就是將數(shù)據(jù)model的值顯示到視圖上面丽猬,model改變時(shí)自動(dòng)更新視圖宿饱,視圖改變時(shí)自動(dòng)更新model;在dataBinding中通過BaseObservable和@={}來實(shí)現(xiàn)脚祟,注意不是@{}(賦值)谬以,是@={}
public class FormModel extends BaseObservable {
private String userName;
private String passWord;
public FormModel() {
}
public FormModel(String userName, String passWord) {
this.userName = userName;
this.passWord = passWord;
}
@Bindable
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
notifyPropertyChanged(BR.userName);
}
@Bindable
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
notifyPropertyChanged(BR.passWord);
}
}
數(shù)據(jù)model的寫法還是和BaseObservable視圖自動(dòng)更新寫法一樣的;
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="formmodel"
type="com.lsm.databindingtest.FormModel"/>
<variable
name="commitFrom"
type="com.lsm.databindingtest.TwoWayActivity.CommitFrom"/>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入用戶名"
tools:ignore="MissingConstraints"
android:inputType="textNoSuggestions"
android:text="@={formmodel.userName}"/>
<EditText
android:id="@+id/et_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="請輸入密碼"
tools:ignore="MissingConstraints"
android:inputType="textNoSuggestions"
android:text="@={formmodel.passWord}"
app:layout_constraintTop_toBottomOf="@+id/et_name"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交"
tools:ignore="MissingConstraints"
app:layout_constraintTop_toBottomOf="@+id/et_pwd"
android:onClick="@{commitFrom.commitFrom}"/>
</android.support.constraint.ConstraintLayout>
</layout>
public class TwoWayActivity extends AppCompatActivity {
private ActivityTwoWayBinding binding;
private FormModel formmodel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding= DataBindingUtil.setContentView(this,R.layout.activity_two_way);
formmodel=new FormModel("111","222");
binding.setFormmodel(formmodel);
binding.setCommitFrom(new CommitFrom());
formmodel.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
@Override
public void onPropertyChanged(Observable sender, int propertyId) {
//監(jiān)聽發(fā)送改變
}
});
}
public class CommitFrom{
public void commitFrom(View view){
Toast.makeText(TwoWayActivity.this,formmodel.getUserName()+"----"+formmodel.getPassWord(),Toast.LENGTH_LONG).show();
}
}
}
在activity中還可以通過addOnPropertyChangedCallback來監(jiān)聽視圖的改變由桌;
這樣就實(shí)現(xiàn)了數(shù)據(jù)和視圖的雙向綁定为黎,在點(diǎn)擊提交的時(shí)候并沒有做其他操作,就只是做了一個(gè)Toast提示行您;
動(dòng)畫
接下來看下動(dòng)畫的簡單實(shí)現(xiàn)铭乾;
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="persenter"
type="com.lsm.databindingtest.AnimationActivity.Persenter" />
<variable
name="showImage"
type="boolean" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/default_avatar"
android:visibility="@{showImage?View.VISIBLE:View.GONE}"
tools:ignore="MissingConstraints" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onCheckedChanged="@{persenter.onCheckedChanged}"
android:text="圖片顯示或者隱藏"
tools:ignore="MissingConstraints"
app:layout_constraintTop_toBottomOf="@+id/iv"/>
</android.support.constraint.ConstraintLayout>
</layout>
需要注意:不管是不是動(dòng)畫的實(shí)現(xiàn),如果在布局中通過三元運(yùn)算符等操作運(yùn)算符來控制視圖的顯示或者隱藏邑雅,需要在data節(jié)點(diǎn)標(biāo)簽中做引用片橡;
<import type="android.view.View" />
public class AnimationActivity extends AppCompatActivity {
private ActivityAnimationBinding binding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding= DataBindingUtil.setContentView(this,R.layout.activity_animation);
binding.addOnRebindCallback(new OnRebindCallback() {
@Override
public boolean onPreBind(ViewDataBinding binding) {
ViewGroup viewGroup= (ViewGroup) binding.getRoot();
TransitionManager.beginDelayedTransition(viewGroup);
return true;
}
});
binding.setPersenter(new Persenter());
}
public class Persenter{
public void onCheckedChanged(View buttonView, boolean isChanged){
binding.setShowImage(isChanged);
}
}
}
上面這些只是dataBinding的部分用法妈经,更多的用法可以查閱更多的資料進(jìn)行學(xué)習(xí)淮野。
源碼