使用DataBinding需要三个步骤:
1、启用DataBinding
2、修改布局文件为DataBinding布局
把传统的布局替换为dataBinding布局:在外层布局按住Ctrl+回车会提示是否转化成dataBinding布局,直接转化:
3、数据绑定:替换setContentView: 经过上述步骤,系统会自动生成ActivityMainBinding类,类名是布局文件名+Binding,布局文件首字母大写
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="account"
type="com.example.myapplication.databinding.MyAccount" />
<variable
name="activity"
type="com.example.myapplication.MainActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{account.name + '|' + account.level}"
android:textSize="30dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp" />
<Button
android:id="@+id/bt"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="加1"
android:textSize="20dp"
android:layout_gravity="center_horizontal"
android:onClick="@{activity.onClick}"
android:layout_marginTop="40dp" />
</LinearLayout>
</layout>
public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding;
MyAccount mAccount;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
// binding.textView.setText("你好");
mAccount = new MyAccount();
mAccount.setLevel("1");
mAccount.setName("dongjie");
binding.setAccount(mAccount);
binding.setActivity(this);
}
public void onClick(View v) {
Toast.makeText(this, "点击", Toast.LENGTH_LONG).show();
// binding.setAccount(mAccount);
// binding.textView.setText("aaaaa");
mAccount = new MyAccount();
mAccount.setLevel("2");
mAccount.setName("dongjiejie");
binding.setAccount(mAccount);
}
}
经过上述步骤,修改数据就可以自动更新到界面上了。
上面的方法还可以优化,当数据变化的时候,自动更新界面数据:
1、继承BaseObservable
2、get方法添加@Bindable
3、set方法添加notifyPropertyChanged(BR.name);
package com.example.myapplication.databinding;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import com.example.myapplication.BR;
public class MyAccount extends BaseObservable {
String name;
String level;
@Bindable
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
// 当name发生变化的时候,更新界面数据, BR是DataBinding生成的,类似于R
notifyPropertyChanged(BR.name);
}
@Bindable
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
notifyPropertyChanged(BR.level);
}
}
经过上述步骤,上面的onClick方法就可以这么写:改变数据源以后会自动同步到界面上
public void onClick(View v) {
mAccount.setLevel("2");
mAccount.setName("dongjiejie");
}
到目前为止都是单向绑定,数据更新以后会直接同步到界面上,在@后面加等号就是双向绑定了,一般用的比较多得是输入框
MVVM实现需求需要以下几个步骤:
下面给一个完整的demo:
SecondActivity.java 和activity_second.xml
package com.example.myapplication.databinding2;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import com.example.myapplication.R;
import com.example.myapplication.databinding.ActivitySecondBinding;
public class SecondActivity extends AppCompatActivity {
ActivitySecondBinding mBinding;
MVVMViewModel mVVMViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_second);
mVVMViewModel = new MVVMViewModel(getApplication(), mBinding);
// 在xml里的变量都得初始化
mBinding.setViewModel(mVVMViewModel);
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<!-- 声明MVVMViewModel,在activity中初始化 -->
<variable
name="viewModel"
type="com.example.myapplication.databinding2.MVVMViewModel" />
<variable
name="activity"
type="com.example.myapplication.MainActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/edit_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:textSize="30dp"
android:text="@={viewModel.inputStr}"
android:layout_marginTop="30dp" />
<!--注意设置点击事件,不能带括号,只写方法名-->
<Button
android:id="@+id/bt"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="点击"
android:textSize="20dp"
android:layout_gravity="center_horizontal"
android:onClick="@{viewModel.getData}"
android:layout_marginTop="40dp" />
<TextView
android:id="@+id/text_view"
android:textSize="20dp"
android:textColor="#000"
android:layout_marginTop="30dp"
android:layout_gravity="center_horizontal"
android:layout_width="match_parent"
android:text="@{viewModel.result}"
android:layout_height="wrap_content"/>
</LinearLayout>
</layout>
MVVMViewModel.java
这一层相当于MVP的Presenter,处理逻辑,它里面调用Model层来请求数据,然后通过DataBinding来设置到界面上,如果遇到请求权限等操作,此层可以持有Activity的对象,或者用EventBus也可以, 不过一般不要这么做,一般用LiveData+ViewModel的方式来做。
package com.example.myapplication.databinding2;
import android.app.Application;
import android.view.View;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import com.example.myapplication.BR;
import com.example.myapplication.databinding.ActivitySecondBinding;
// MVVMViewModel相当于MVP的Presenter,处理业务逻辑
public class MVVMViewModel extends BaseObservable {
Application application;
ActivitySecondBinding mBinding;
String result;
String inputStr;
MVVMModel mModel;
public MVVMViewModel(Application application) {
this.application = application;
mModel = new MVVMModel();
}
public MVVMViewModel(Application application, ActivitySecondBinding binding) {
this(application);
mBinding = binding;
}
public void getData(View v) {
// String editStr = mBinding.editView.getText().toString();
// String ret = mModel.getScreenData(editStr);
// setResult(ret); // 必须调用setResult才能更新
// 因为inputStr和控件是双向绑定,所以输入的时候inputStr是最新值,这样就不用传ActivitySecondBinding参数
String ret = mModel.getScreenData(inputStr);
setResult(ret);
}
@Bindable
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
notifyPropertyChanged(BR.result);
}
@Bindable
public String getInputStr() {
return inputStr;
}
public void setInputStr(String inputStr) {
this.inputStr = inputStr;
notifyPropertyChanged(BR.inputStr);
}
}
MVVMModel.java
这里模拟请求数据,一般是通过回调返回数据给MVVMViewModel的,这里为了简单写了同步方法
package com.example.myapplication.databinding2;
import com.example.myapplication.databinding.ActivitySecondBinding;
public class MVVMModel {
public MVVMModel() {
}
public String getScreenData(String inputStr) {
String str = "请求参数:" + inputStr + "\n请求数据:谢谢谢谢谢寻寻寻寻寻";
return str;
}
}