Android Jetpack 之data-binding

使用入门

了解如何准备开发环境以使用数据绑定库,包括支持 Android Studio 中的数据绑定代码。

数据绑定库不但灵活,而且兼容性广,它是一个支持库,因此您可以在运行 Android 4.0(API 级别 14)或更高级别的设备上使用它。

建议您在项目中使用最新的 Android Plugin for Gradle。不过,1.5.0 版及更高版本支持数据绑定。有关详情,请参阅介绍如何更新 Android Plugin for Gradle的说明。

编译环境

要开始使用数据绑定,请从 Android SDK 管理器中的支持代码库下载该库。有关详情,请参阅更新 IDE 和 SDK 工具

要将应用配置为使用数据绑定,请在应用模块的 build.gradle 文件中添加 dataBinding 元素,如以下示例所示:

android {
        ...
        dataBinding {
            enabled = true
        }
    }

注意:即使应用模块不直接使用数据绑定,也必须为依赖于使用数据绑定的库的应用模块配置数据绑定。 

在build.gradle加入依赖

dependencies {      

... implementation 'androidx.databinding:databinding-common:4.1.3'

}

单向和双向绑定

定义观察者

public class Person extends BaseObservable {
    //双向绑定
    private ObservableField<String> name = new ObservableField<>();
    //单向绑定
    private int age;

    public Person(String name) {
        this.name.set(name);
        this.setAge(10);
    }

    public ObservableField<String> getName() {
        return name;
    }

    public void setName(ObservableField<String> name) {
        this.name = name;
    }

    @Bindable
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
        notifyPropertyChanged(BR.age);
    }
    //事件绑定
    public void onBtnClick(View view) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                setAge(20);
                name.set("李四");
            }
        });
        Log.d("Person", String.format("test->name=%s", name.get()));
    }
}
修改layout

<?xml version="1.0" encoding="utf-8"?>
<!--数据绑定根节点必须是layout-->
<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>
        <import type="com.example.myapplication.model.Person"></import>
        <variable
            name="person"
            type="Person" />
    </data>
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <!--包含其它layout传递person -->
        <include app:person="@{person}" layout="@layout/content_main" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            app:srcCompat="@android:drawable/ic_dialog_email" />

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center">
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <!-- 双向绑定-->
                <EditText
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:text="@={person.name}"></EditText>
                <!-- 单向绑定-->
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@{Integer.toString(person.age)}"></TextView>
                <!-- 绑定事件-->
                <Button
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="test"
                    android:onClick="@{person::onBtnClick}"></Button>
            </LinearLayout>

        </RelativeLayout>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
Activity中设置数据源,ActivityMainBinding 为按照命名规则(以Activity或Fragment开头,Binding结尾)自动生成类对象
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        setContentView(binding.getRoot());
        
        Person person = new Person("abc");
        //设置数据源
        binding.setPerson(person);
}

Fragment中设置数据源

 @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout for this fragment
//        return inflater.inflate(R.layout.fragment_first, container, false);
        FragmentFirstBinding binding = DataBindingUtil.inflate(inflater,R.layout.fragment_first,container,false);
        person =new Person("张三");
        binding.setPerson(person);

        View mainView = binding.getRoot();
        textView = mainView.findViewById(R.id.textViewTest);

        return mainView;
    }

自定义控件数据绑定

继续上面例子继续增加功能

 attrs声明

  <declare-styleable name="CustomControl">
        <attr name="nLabel" format="string"></attr>
        <attr name="nValue" format="string"></attr>
    </declare-styleable>

layout文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:gravity="center">
        <TextView
            android:id="@+id/textViewLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="label"></TextView>
        <EditText
            android:id="@+id/editTextValue"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="value"
            android:layout_marginLeft="10dp"></EditText>
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
CustomControl实现
package com.example.myapplication.controls;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.databinding.BindingAdapter;
import androidx.databinding.InverseBindingAdapter;
import androidx.databinding.InverseBindingListener;

import com.example.myapplication.R;

public class CustomControl extends ConstraintLayout implements TextWatcher{
    static String tag="CustomControl";
    public interface Listener {
        void onTextChanged(String password);
    }
    protected TextView textViewLabel;
    protected EditText editTextValue;
    protected String text;
    protected Listener listener;
    protected InverseBindingListener textInverseBindingListener;
    public CustomControl(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater li = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
        li.inflate(R.layout.layout_custom_control, this, true);

        textViewLabel = findViewById(R.id.textViewLabel);
        editTextValue = findViewById(R.id.editTextValue);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomControl);
        String label = ta.getString(R.styleable.CustomControl_nLabel);
        String value = ta.getString(R.styleable.CustomControl_nValue);

        textViewLabel.setText(label);
        editTextValue.setText(value);
        text= value;

        editTextValue.addTextChangedListener(this);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if(s==null){
            text="";
            return;
        }
        String str = s.toString();
        if(str.equals(text)){
            return;
        }
        text = str;
        editTextValue.setSelection(str.length());
        if (listener != null)
            listener.onTextChanged(str);

        if(this.textInverseBindingListener !=null){
            this.textInverseBindingListener.onChange();
        }
    }

    @Override
    public void afterTextChanged(Editable s) {

    }

    public void setListener(Listener listener) {
        this.listener = listener;
    }

    public String getText() {
        return text;
    }
    public void setText(String text){
        if(this.text!=null && this.text.equals(text)){
            return;
        }
        this.text = text;
        this.editTextValue.setText(text);
        this.editTextValue.setSelection(text==null?0:text.length());
    }
    @BindingAdapter({"vendorText"})
    public static void setText(CustomControl view, String userPassword) {
        view.setText(userPassword);
        Log.d(tag, String.format("setText->%s",userPassword));
    }

    @BindingAdapter(value = {"textAttrChanged"}, requireAll = false)
    public static void setTextAttrChanged(CustomControl view, InverseBindingListener inverseBindingListener) {
        if (inverseBindingListener == null) {
            Log.e(tag, "setTextAttrChanged->InverseBindingListener is null");
        } else {
            view.textInverseBindingListener = inverseBindingListener;
        }
    }

    @InverseBindingAdapter(attribute = "vendorText", event = "textAttrChanged")
    public static String getText(CustomControl view) {
        return view.getText().toString();
    }

}

MainActivity的layout

<com.example.myapplication.controls.CustomControl
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    app:nLabel="姓名"
                    app:nValue="李四"
                    app:vendorText="@={person.name}"></com.example.myapplication.controls.CustomControl>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值