一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
一.简介
DataBinding是谷歌发布的一个实现数据和UI绑定的框架,从字面意思来看即为数据绑定,是 MVVM 模式在Android上的一种实现,用于降低布局和逻辑的耦合性,使代码逻辑更加清晰。
相对于 MVP,MVVM将Presenter层替换成了ViewModel层,关于MVC、MVP、MVVM架构比较,这里就不赘述了。
DataBinding 能够省去我们一直以来的 findViewById() 步骤,大量减少 Activity 内的代码,数据能够单向或双向绑定到 layout 文件中。
接下来本文通过一个例子来学习一下DataBinding的用法及原理分析。
二.实例分析
a.加入dataBinding支持
使用DataBinding框架需要在对应Model的build.gradle文件Android{}内加入以下代码,同步后就能引入对 DataBinding的支持:
dataBinding {
enabled = true
}
AndroidStudio高版本引入方式如下:
buildFeatures {
dataBinding = true
}
b.xml布局文件转化
将常规的布局文件转化为对应的数据绑定布局文件,在布局文件的根布局上输入Alt+Enter后,选择Convert to data binding 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">
<data>
//布局文件用到了View相关的方法,需要引入
<import type="android.view.View" />
<variable
//任意取名字,来作为type对应的引用,可以通过guide代替类取可变变量
//在view中通过setGuide()建立引用关系
name="guide"
//定义可变变量的类
type="com.xxx.learn.ViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/name"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:gravity="center"
android:textColor="@android:color/holo_red_light"
android:text="@{guide.rightImageName}" />
<ImageView
android:layout_width="200dp"
android:layout_height="160dp"
android:layout_below="@+id/name"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:scaleType="fitXY"
android:src="@{guide.rightImageRes}" />
<TextView
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_below="@+id/name"
android:layout_centerHorizontal="true"
android:layout_marginTop="200dp"
android:textColor="@color/colorAccent"
android:text="@{guide.rightImageDescription}" />
<TextView
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_below="@+id/name"
android:layout_marginLeft="50dp"
android:layout_marginTop="350dp"
android:gravity="center"
android:onClick="@{guide::upStep}"
android:text="@string/up"
android:textStyle="bold"
android:textColor="@color/cardview_shadow_start_color"
android:visibility="@{guide.step!=1?View.VISIBLE:View.INVISIBLE}" />
<TextView
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_below="@+id/name"
android:layout_marginLeft="230dp"
android:layout_marginTop="350dp"
android:gravity="center"
android:onClick="@{guide::nextStep}"
android:text="@string/next"
android:textStyle="bold"
android:visibility="@{guide.step!=3?View.VISIBLE:View.INVISIBLE}" />
</RelativeLayout>
</layout>
通过以上转化,已经将常规布局转化为数据绑定布局文件,那么下面就一步一步的来讲解实现。
c.View逻辑实现
将之前常规的UI操作从view里面移到数据绑定布局xml文件中,可以大大减少view的代码量及相关的UI操作逻辑。
使用前,动态设置ImageView的显示,在view里面的操作如下:
ImageView mImg = findViewById(R.id.img);
mImg.setImageResource(R.drawable.rse);
使用databinding后,可以在布局文件中将布局变量赋值以@{}形式给ImageView的src属性。当rightImageRes变化时,ImageView会动态加载对应的资源文件。
<ImageView
android:layout_width="200dp"
android:layout_height="160dp"
android:layout_below="@+id/name"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:scaleType="fitXY"
android:src="@{guide.rightImageRes}" />
使用数据绑定布局文件后,view对应的类变为:
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.xxx.learn.ViewModel;
import com.xxx.learn.databinding.KeyboardLayoutBinding;
import com.xxx.learn.R;
import androidx.databinding.DataBindingUtil;
public class KeyboardFragment extends BaseFragment {
private ViewModel mViewModel;
@Override
public int getLayoutId() {
return R.layout.keyboard_layout;
}
@Override
public void initData(View view) {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//-------------------分析1------------------------------------
KeyboardLayoutBinding binding = DataBindingUtil.inflate(inflater, R.layout.keyboard_layout, container, false);
//获取布局对应的view
//--------------------分析2-----------------------------------
View view = binding.getRoot();
//-------------------分析3----------------------------------
mViewModel = new ViewModel(mContext);
binding.setGuide(mViewModel);
//-------------------分析4----------------------------------
view.viewpager.setAdapter(xx);
return view;
}
}
通过以上可以发现,主要的分析点如下:
分析1:通过DataBindingUtil来替代inflater来解析数据绑定布局文件,KeyboardLayoutBinding是在编译时根据keyboard_layout生成的(后面会有详细分析);如果为Activity,通过setContentView()方法来解析生成KeyboardLayoutBinding;
分析2:通过getRoot()获取布局文件对应的View;
分析3:创建ViewModel,并通过setGuide()(名字不是固定的)将View与ViewModel里面的变量建立关联;
分析4:直接通过view.idName来获取对应的view,然后进行操作;
使用了数据绑定布局后,view里面除了加载布局后,没有任何相关的findViewById操作,确实减少了不少UI处理逻辑。