Jetpack_dataBinding

开始使用

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的引用

  1. 在activity中
	//绑定类名 = 布局名称(转换为驼峰) + Binding
	ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
  1. 在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);
        }
    }
    
}
解读
  1. 上图相当于给Binding布局中的 ImageView标签 添加 imageUrl属性imageLocal属性

  2. 其中 ImageView标签源于方法的第一个参数

  3. imageUrl属性 和 imageLocal属性 源于 BindingAdapter注解中的两个value值

  4. BindingAdapter注解中value值 接收的是一个数组,意味着可以给 ImageView标签 添加任意个数的属性

  5. requireAll : true: 默认, 如果声明的value没有被全部设置,则无法编译 false: 允许只有部分值被设置

  6. 通过绑定适配器,可以将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);
    }
}

上一篇:数据绑定 DataBinding


下一篇:《重学安卓》两周内,回顾与展望