开始使用
1. 在moudle的build.gradle中开启对databinding的支持
defaultConfig {
applicationId "com.example.databinding_viewmodel_livedata"
minSdkVersion 15
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//开启对databinding的支持
dataBinding{
enabled = true
}
}
2. 在布局文件中添加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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.example.databinding_viewmodel_livedata.MyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
3. 获取dataBinding的引用
- 在activity中
//绑定类名 = 布局名称(转换为驼峰) + Binding
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
- 在fragment中
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final FragmentFirstBinding fragmentFirstBinding = DataBindingUtil.inflate(inflater,R.layout.fragment_first,container,false);
return fragmentFirstBinding.getRoot();
}
两个常用的标签
1.声明标签
<data>
<variable
name="viewModel"
type="com.example.databinding_viewmodel_livedata.MyViewModel" />
</data>
表示在layout布局文件中,声明一个变量
变量的类型: com.example.databinding_viewmodel_livedata.MyViewModel
变量的名称: viewModel
变量由 DataBinding对象 赋值 :
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
activityMainBinding.setViewModel(myViewModel);
2.导入标签
<data>
<import type="com.example.databinding_viewmodel_livedata.AppUtils"
alias="appUtils"/>
</data>
表示在layout布局文件中,导入一个类
alias=“appUtils” : 给类起别名 (可不设置)
类中存在静态方法: madeNewScore(int score) ,可直接调用:
<TextView
android:id="@+id/tvScore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{appUtils.madeNewScore(viewModel.score)}"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
在include中使用
1.创建文件名称为 include_layout 的 include布局
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="includeViewModel"
type="com.example.databinding_viewmodel_livedata.MyViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{String.valueOf(includeViewModel.num)}"
android:textSize="22sp" />
</LinearLayout>
</layout>
2.使用include布局
<include
app:includeViewModel="@{viewModel}"
layout="@layout/include_layout"
/>
includeViewModel : 在include布局文件定义的 变量名称
app:includeViewModel="@{viewModel}": 将该布局数的viewModel变量 赋值给 include布局中的includeViewModel变量
事件处理
方法绑定
相似于给view添加onClick()方法
public class MyHandlers {
public void onClickFriend(View view) { ... }
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="handlers" type="com.example.MyHandlers"/>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"
android:onClick="@{handlers::onClickFriend}"/>
</LinearLayout>
</layout>
监听器绑定 (常用,且可在监听回调中传入任意个数的参数)
public class Presenter {
public void onSaveClick(Task task){}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="task" type="com.android.example.Task" />
<variable name="presenter" type="com.android.example.Presenter" />
</data>
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:layout_width="wrap_content" android:layout_height="wrap_content"
android:onClick="@{() -> presenter.onSaveClick(task)}" />
</LinearLayout>
</layout>
绑定适配器
此处示例实现了 LiveData + ViewModel + DataBinding 的结合
意义: 实现了单向绑定, 当ViewModel中的值(LiveData包裹)发生变化时,界面会自动发生变化
创建绑定适配器
public class BindingAdapterManager {
@BindingAdapter(value = {"imageUrl","imageLocal"},requireAll = false)
public static void setImage(ImageView imageView,String imageUrl,int resId){
if (!TextUtils.isEmpty(imageUrl)){
Glide.with(imageView.getContext()).load(imageUrl).into(imageView);
}else {
Glide.with(imageView.getContext()).load(resId).into(imageView);
}
}
}
解读
-
上图相当于给Binding布局中的 ImageView标签 添加 imageUrl属性 和 imageLocal属性
-
其中 ImageView标签源于方法的第一个参数
-
imageUrl属性 和 imageLocal属性 源于 BindingAdapter注解中的两个value值
-
BindingAdapter注解中value值 接收的是一个数组,意味着可以给 ImageView标签 添加任意个数的属性
-
requireAll : true: 默认, 如果声明的value没有被全部设置,则无法编译 false: 允许只有部分值被设置
-
通过绑定适配器,可以将View的一些属性的设置实现复用 ,并与业务逻辑实现解耦
在布局中的使用
<?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="viewModel"
type="com.example.databinding_viewmodel_livedata.MyViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="40dp"
tools:context=".MainActivity">
<ImageView
app:imageUrl="@{viewModel.imgUrl}"
app:imageLocal="@{viewModel.imgLocalResId}"
android:layout_width="match_parent"
android:layout_height="200dp"/>
</LinearLayout>
</layout>
对应的ViewModel
public class MyViewModel extends ViewModel {
private MutableLiveData<Integer> imgLocalResId;
private MutableLiveData<String> imgUrl;
public MutableLiveData<Integer> getImgLocalResId() {
if (imgLocalResId==null){
imgLocalResId = new MutableLiveData<>();
imgLocalResId.setValue(R.mipmap.idol);
}
return imgLocalResId;
}
public MutableLiveData<String> getImgUrl() {
if (imgUrl==null){
imgUrl = new MutableLiveData<>();
imgUrl.setValue(
"http://wx1.sinaimg.cn/mw2000/007fS0GEgy1gs59xp5cwfj60tw1a810v02.jpg"
);
}
return imgUrl;
}
}
在Activity中的使用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建databinding对象
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
//获取ViewModel对象
MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
//设置dataBinding的变量的值
activityMainBinding.setViewModel(myViewModel);
//不设置无法实现单向绑定
activityMainBinding.setLifecycleOwner(this);
}
}