DataBinding在Android中的使用

2021-01-01  本文已影响0人  放羊娃华振

一、概述

DataBinding可以实现数据单向或者双向的绑定,让开发比较方便。通过数据变化更新UI,完全由数据驱动。

二、使用

1、集成DataDinding

添加 dataBinding.enabled true 和 dataBinding { enabled = true }
示例如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.1"
    defaultConfig {
        applicationId "com.stormdzh.myapplication"
        minSdkVersion 15
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        dataBinding.enabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    //添加这行就算引入了
    dataBinding {
        enabled = true
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

    implementation 'com.facebook.fresco:fresco:2.3.0'
}
2、实现xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="title"
            type="java.lang.String" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:textColor="#000000"
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{title}"/>
    </LinearLayout>

</layout>
3、Activity中添加测试代码
public class TestDataBindingActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityTestDatabindingBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_test_databinding);
        //setContentView(R.layout.activity_test_databinding);
        viewDataBinding.setLifecycleOwner(this);
        viewDataBinding.setTitle("测试字符串");
    }
}
4、集成中问题

1.Activity需要集成AppCompatActivity
2.写完DataBindingUtil.setContentView(this, R.layout.activity_test_databinding)后,可以输入ActivityTestDatab...让编译器不全这个变量。这个变量是Android生成的,自己手写可能会有误差。

三、常用知识

1、引入对象

需要把类引入进来,之后给他设置一个name。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="title"
            type="java.lang.String" />
         <variable
             name="user"
             type="com.stormdzh.myapplication.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:textColor="#000000"
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{title}"/>


        <TextView
            android:textColor="#000000"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"/>
    </LinearLayout>

</layout>
2、引入静态方法

需要把工具类引入进来,之后通过@{AppUtil.int2Str(user.age)}调用

public class AppUtil {

    public static String  int2Str(int num){

        return String.valueOf(num);
    }
}

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="com.stormdzh.myapplication.AppUtil" />
        <variable
            name="title"
            type="java.lang.String" />
         <variable
             name="user"
             type="com.stormdzh.myapplication.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:textColor="#000000"
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{title}"/>


        <TextView
            android:textColor="#000000"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"/>

        <TextView
            android:textColor="#000000"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{AppUtil.int2Str(user.age)}"/>
    </LinearLayout>

</layout>

3、DataBinding中引入数据的另一种形式
 <data>
        <import type="java.lang.String"/>
        <import type="com.stormdzh.myapplication.User"
            alias="User"/>
        <variable name="title" type="String" />
        <variable name="user" type="User" />
    </data>
4、如何使用data中引入和定义的内容

1.variable——使用variable中的bean对象,如果是属性,直接使用@{name.field}

<TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@{user.name}" />

2.如果使用的无参数方法,@{() -> name.function()}

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{() -> listener.onClickListenerBinding()}"
            android:text="@{Utility.autoAppend(v,user.name)}" />

3.点击事件需要把点击的view传入并操作,@{(v) -> name.function(v)} 括号中间的v就表示当前的这个view的参数名称(可以自定义),直接作为参数名使用就可以。

<TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{(v) -> listener.onClickListenerBinding(v)}"
            android:text="@{user.name}" />
5、DataBinding是使用点击事件
//java代码
public class TestDataBindingActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityTestDatabindingBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_test_databinding);
//        setContentView(R.layout.activity_test_databinding);
        viewDataBinding.setLifecycleOwner(this);
        viewDataBinding.setTitle("测试字符串");

        User user = new User();
        user.name="张三";
        user.age=18;
        viewDataBinding.setUser(user);

        user.name="李四";

        //设置点击事件
        viewDataBinding.setEventHandler(new OnEventHandler());

    }

    public class OnEventHandler{
        public void onClick(View v){
            Toast.makeText(TestDataBindingActivity.this,"响应了点击事件",Toast.LENGTH_SHORT).show();
        }
    }
}

//布局文件 
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="com.stormdzh.myapplication.AppUtil" />

        <variable
            name="title"
            type="java.lang.String" />

        <variable
            name="user"
            type="com.stormdzh.myapplication.User" />

        <variable
            name="eventHandler"
            type="com.stormdzh.myapplication.TestDataBindingActivity.OnEventHandler" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:onClick="@{(v)->eventHandler.onClick(v)}"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:background="#543298"
            android:gravity="center"
            android:text="更新数据"
            android:textColor="#000000" />

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{title}"
            android:textColor="#000000" />


        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"
            android:textColor="#000000" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{AppUtil.int2Str(user.age)}"
            android:textColor="#000000" />
    </LinearLayout>

</layout>
6、include使用

系统会自动生成一个自定义属性bind,通过bind可以直接对include中的layout中绑定的数据直接进行赋值,这样就可以间接的控制include中的操作。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:bind="http://schemas.android.com/apk/res-auto">
   <data>
       <variable name="user" type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <include layout="@layout/name"
           bind:user="@{user}"/>
       <include layout="@layout/contact"
           bind:user="@{user}"/>
   </LinearLayout>
</layout>
7、ViewStub使用

首先ViewStub在尚未添加到xml中时,获取Bindgin对象肯定是无效的,所以需要在OnInflateListener中回调被添加的事件,然后再去获Bing对象。

binding = DataBindingUtil.setContentView(this, R.layout.activity_view_stub);
binding.viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {
    @Override
    public void onInflate(ViewStub stub, View inflated) {
        ViewStubBinding binding = DataBindingUtil.bind(inflated);
        User user = new User("name", "刘备");
        binding.setUser(user);
    }
});

四、绑定可观察数据;绑定可观察数据由三种方式:object,field,collections。

1、继承BaseObservable,当数据发生变化的时候调用:notifyChange方法

public class User extends BaseObservable {
    public String name;
    public int age;
}

//模拟数据变化
public class OnEventHandler{
        public void onClick(View v){
            Toast.makeText(TestDataBindingActivity.this,"响应了点击事件",Toast.LENGTH_SHORT).show();
            user.name="阿波罗";
            user.notifyChange();
        }
    }

2、一个对象中只有一个或者几个变量需要观察变化,比如age需要变化

public class User {
    public String name;
    //把int改为ObservableInt
    public ObservableInt age;
}

对于基本类型和Parcelable我们可以直接使用对应的包装类:

ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
ObservableDouble
ObservableParcelable

之后再Activity通过修改ObservableInt的值,在调用notifyChange更新

public class TestDataBindingActivity extends AppCompatActivity {

    private User user;
    ObservableInt observableAge = new ObservableInt(18);

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityTestDatabindingBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_test_databinding);
//        setContentView(R.layout.activity_test_databinding);
        viewDataBinding.setLifecycleOwner(this);
        viewDataBinding.setTitle("测试字符串");

        user = new User();
        user.name = "张三";
        user.age = observableAge;
        viewDataBinding.setUser(user);

        //设置点击事件
        viewDataBinding.setEventHandler(new OnEventHandler());
    }

    public class OnEventHandler {
        public void onClick(View v) {
            Toast.makeText(TestDataBindingActivity.this, "响应了点击事件", Toast.LENGTH_SHORT).show();
            user.name = "阿波罗";
            observableAge.set(90);
            observableAge.notifyChange();
        }
    }
}

四、LiveData+DataBinbing

实体类:

public class Person {
    public String name;
    public int age;
}

Xml文件

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="liveData"
            type="androidx.lifecycle.MutableLiveData&lt;com.stormdzh.myapplication.Person>" />

        <variable
            name="eventHandler"
            type="com.stormdzh.myapplication.LiveDataEntityBindingActivity.OnEventHandler" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:onClick="@{(v)->eventHandler.onClick(v)}"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:background="#543298"
            android:gravity="center"
            android:text="更新数据"
            android:textColor="#000000" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{liveData.name}"
            android:textColor="#000000" />

    </LinearLayout>
</layout>

java类的实现

public class LiveDataEntityBindingActivity extends AppCompatActivity {

    MutableLiveData<Person> mutableLiveData;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityEntityLiveDatabindingBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_entity_live_databinding);
        viewDataBinding.setLifecycleOwner(this);
        mutableLiveData =new MutableLiveData<>();
        //设置点击事件
        viewDataBinding.setEventHandler(new OnEventHandler());
        viewDataBinding.setLiveData(mutableLiveData);
        Person p =new Person();
        p.name= "首次";
        mutableLiveData.setValue(p);
    }

    public class OnEventHandler {
        public void onClick(View v) {
            Toast.makeText(LiveDataEntityBindingActivity.this, "响应了点击事件", Toast.LENGTH_SHORT).show();
            Person p =new Person();
            p.name= "更新";
            mutableLiveData.setValue(p);
        }
    }
}

五、双向绑定

上述的单向绑定是数据变化后更新UI,而双向绑定是指其中任意一个变化后都会同步更新到另一个。双向绑定使用@={}表达式来实现:

<data>
...
   <variable name="input" type="androidx.databinding.ObservableField&lt;String"/>
    </data>
...
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={input}"/>

目前已经支持双向绑定的列表:


image.png

六、DataBinding加载图片

Xml文件实现逻辑

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <import type="com.stormdzh.myapplication.AppUtil" />

        <variable
            name="imageUrl"
            type="java.lang.String" />

        <variable
            name="eventHandler"
            type="com.stormdzh.myapplication.PicDataBindingActivity.OnEventHandler" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:background="#543298"
            android:gravity="center"
            android:onClick="@{(v)->eventHandler.onClick(v)}"
            android:text="更新数据"
            android:textColor="#000000" />

        <com.facebook.drawee.view.SimpleDraweeView
            imageUrl="@{imageUrl}"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="10dp" />

    </LinearLayout>
</layout>

java代码实现

public class PicDataBindingActivity extends AppCompatActivity {


    ActivityPicDatabindingBinding viewDataBinding;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_pic_databinding);
//        setContentView(R.layout.activity_test_databinding);
        viewDataBinding.setLifecycleOwner(this);

        //设置点击事件
        viewDataBinding.setEventHandler(new OnEventHandler());

        String path = "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1089874897,1268118658&fm=26&gp=0.jpg";
        viewDataBinding.setImageUrl(path);

    }


    public class OnEventHandler {
        public void onClick(View v) {
            Toast.makeText(PicDataBindingActivity.this, "响应了点击事件", Toast.LENGTH_SHORT).show();

            String path = "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1056193884,1712488622&fm=26&gp=0.jpg";
            viewDataBinding.setImageUrl(path);
        }
    }

    @BindingAdapter("imageUrl")
    public static void loadImage(SimpleDraweeView iv, String imageUrl) {
        Log.i("dzh", "加载图片了");
        loadPic(iv, imageUrl);
    }

    private static void loadPic(SimpleDraweeView mSimpleDraweeView, String path) {

        Uri uri = Uri.parse(path);
        mSimpleDraweeView.setImageURI(uri);
    }


}

五、总结

DataBing还有很多知识点需要完善,但是大致的要点都介绍了。现在也都晚上9点多了,有点写不动了,以后再花点时间好好整理其中的细节,大家一起共勉!之后奉上Demo源码!

上一篇下一篇

猜你喜欢

热点阅读