美文网首页Android笔记本DataBinding框架【库】
Android dataBinding 的绑定数据、列表、点击事

Android dataBinding 的绑定数据、列表、点击事

作者: 刘孙猫咪 | 来源:发表于2019-04-20 21:03 被阅读81次

    dataBinding是google推出来的一个mvvm的框架,出来有一段时间了,由于之前的项目都是用mvc或者mvp的模式开发,没有使用mvvm模式进行开发,这次公司项目用的是jetpack框架,涉及到ViewModel、dataBinding等,所以就利用些空闲时间了解和学习下dataBinding的一些使用。

    准备工作:

    要使用dataBinding的话,首先要在app model 下build.gradle文件的android节点下添加

    dataBinding{
            enabled=true
        }
    

    如:


    微信截图_20190420184054.png

    数据绑定

    在xml布局中使用dataBinding时,要将xml布局文件的节点进行修改,如:

    <?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>
    
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
        </LinearLayout>
    </layout>
    

    将layout节点放最外面,接着是data节点,在data节点中可以新增variable节点,在data节点下面可以写之前的布局节点;

    <?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>
            <variable
                name="employee"
                type="com.lsm.databindingtest.Employee" />
        </data>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <TextView
                android:id="@+id/first_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="10dp"
                android:text="@{employee.firstName}" />
            <TextView
                android:id="@+id/last_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="10dp"
                android:text="@{employee.lastName}" />
        </LinearLayout>
    </layout>
    

    variable节点中name是type的一个名称,type是对应model类的包名路径,通过@{}的方式对TextView进行赋值;在activity文件中通过DataBindingUtil进行引用;

    public class SimpleActivity extends AppCompatActivity {
        private ActivitySimpleBinding binding;
        private Employee employee = new Employee("Zhai", "Mark");
        private Worker worker = new Worker("1111", "2222");
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = DataBindingUtil.setContentView(this, R.layout.activity_simple);
            //通过直接赋值
    //        binding.firstName.setText(employee.getFirstName());
    //        binding.lastName.setText(employee.getLastName());
    //        binding.setEmployee(employee);
            binding.setVariable(BR.employee, employee);
        }
    }
    

    ActivitySimpleBinding命名:布局文件名称(第一字母大写,遇到,去掉并将首字母大写)+Binding;
    这里赋值有三种方式:

    1、通过ActivitySimpleBinding.控件id,直接赋值;
    如:binding.firstName.setText(employee.getFirstName());
    
    2、ActivitySimpleBinding调用set方法;
    如:binding.setEmployee(employee);
    
    3、ActivitySimpleBinding调用setVariable方法;
    binding.setVariable(BR.employee, employee);
    
    微信截图_20190420185803.png

    事件绑定

    事件可以通过方法或者监听器的形式来实现;
    在对应的activity中声明一个事件的内部类,在内部类中定义对应的事件方法,在xml布局中通过新增variable节点,对它的name和type属性进行设置,也是用过@{}的方式绑定事件;

    <?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>
            <variable
                name="eventlistener"
                type="com.lsm.databindingtest.SimpleActivity.EventListener" />
        </data>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:onClick="@{eventlistener.clickFirst}"
                android:text="点击(方法)" />
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:onClick="@{(view)->eventlistener.btnClick(view)}"
                android:text="点击(监听器)" />
            <Button
                android:id="@+id/longc"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:onLongClick="@{eventlistener::onLongClick}"
                android:text="长按" />
        </LinearLayout>
    </layout>
    
    public class SimpleActivity extends AppCompatActivity {
        private ActivitySimpleBinding binding;
        private Employee employee = new Employee("Zhai", "Mark");
        private Worker worker = new Worker("1111", "2222");
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = DataBindingUtil.setContentView(this, R.layout.activity_simple);
            binding.setEventlistener(new EventListener());
        }
        public class EventListener {
            public void clickFirst(View view) {
                worker.setFirstName("55555");
                worker.setLastName("7777777");
                Toast.makeText(SimpleActivity.this, "点击了并刷新worker对象的值", Toast.LENGTH_LONG).show();
            }
            public void btnClick(View view){
                Toast.makeText(SimpleActivity.this, "监听器方式", Toast.LENGTH_LONG).show();
            }
            public boolean onLongClick(View view) {
                Toast.makeText(SimpleActivity.this, "长按了", Toast.LENGTH_LONG).show();
                return false;
            }
        }
    }
    

    activity中通过setEventlistener方法传入EventListener对象,setEventlistener方法是自动生成的就可以了;在定义事件方法名称时需要注意:方法的名称可以和之前写法不一样,但是方法名称的参数要和之前的写法一样,不然会报错,比如:clickFirst(View view)必须要有view参数,如果没有会报错

    GIF.gif

    BaseObservable

    BaseObservable在数据发生改变时通知xml布局试图进行刷新

    public class Worker extends BaseObservable {
        private String mLastName;
        private String mFirstName;
        private boolean mIsFired=false;
    
        public Worker(String mLastName, String mFirstName) {
            this.mLastName = mLastName;
            this.mFirstName = mFirstName;
        }
        @Bindable
        public String getLastName() {
            return mLastName;
        }
    
        public void setLastName(String mLastName) {
            this.mLastName = mLastName;
            notifyPropertyChanged(BR.lastName);
        }
        @Bindable
        public String getFirstName() {
            return mFirstName;
        }
    
        public void setFirstName(String mFirstName) {
            this.mFirstName = mFirstName;
            notifyPropertyChanged(BR.firstName);
        }
        @Bindable
        public boolean getFired() {
            return mIsFired;
        }
    
        public void setFired(boolean mIsFired) {
            this.mIsFired = mIsFired;
            //刷新所有有关的ui
    //        notifyChange();
        }
    }
    

    定义一个model类继承自BaseObservable,在get方法上添加@Bindable注解,在set方法中notifyPropertyChanged(BR.lastName)方法更新指定的视图,通过notifyChange();方法更新所有的视图,即使数据没有更新也会重新刷新视图;

    <?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>
            <variable
                name="eventlistener"
                type="com.lsm.databindingtest.SimpleActivity.EventListener" />
            <variable
                name="worker"
                type="com.lsm.databindingtest.Worker"/>
        </data>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:onClick="@{eventlistener.clickFirst}"
                android:text="点击(方法)" />
            <include
                bind:worker="@{worker}"
                layout="@layout/name" />
        </LinearLayout>
    </layout>
    

    name.xml

    <?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>
            <variable
                name="worker"
                type="com.lsm.databindingtest.Worker"/>
        </data>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:layout_gravity="center_horizontal"
                android:text="@{worker.firstName}"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:layout_gravity="center_horizontal"
                android:text="@{worker.lastName}"/>
        </LinearLayout>
    </layout>
    

    点击调用clickFirst方法时改变inclue 中name.xml中的视图;

    public class SimpleActivity extends AppCompatActivity {
        private ActivitySimpleBinding binding;
        private Worker worker = new Worker("1111", "2222");
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = DataBindingUtil.setContentView(this, R.layout.activity_simple);
            binding.setEventlistener(new EventListener());
            binding.setWorker(worker);
        }
        public class EventListener {
            public void clickFirst(View view) {
                worker.setFirstName("55555");
                worker.setLastName("7777777");
                Toast.makeText(SimpleActivity.this, "点击了并刷新worker对象的值", Toast.LENGTH_LONG).show();
            }
        }
    }
    

    在触发点击事件,重新对model进行赋值后,并没有做其他动作,视图就更新了;


    GIF.gif

    include

    在BaseObservable视图更新中其实就提到了include的使用了;

    <?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>
            <variable
                name="worker"
                type="com.lsm.databindingtest.Worker"/>
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <include
                bind:worker="@{worker}"
                layout="@layout/name" />
        </LinearLayout>
    </layout>
    

    name.xml

    <?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>
            <variable
                name="worker"
                type="com.lsm.databindingtest.Worker"/>
        </data>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:layout_gravity="center_horizontal"
                android:text="@{worker.firstName}"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:layout_gravity="center_horizontal"
                android:text="@{worker.lastName}"/>
        </LinearLayout>
    </layout>
    

    activity中的逻辑和上面都差不多,这里就不说了;

    ViewStub

    有时候在项目开发中会使用ViewStub进行加载视图,看看在dataBinding中如何使用ViewStub;

    <?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>
        
        </data>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <ViewStub
                android:id="@+id/view_stub"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout="@layout/viewstub"/>
        </LinearLayout>
    </layout>
    

    viewstub.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher_round"/>
    </LinearLayout>
    
    微信截图_20190420201614.png

    和之前的使用一样没有区别;

    RecyclerView

    在开发过程中列表(RecyclerView,ListView,GridView等)的使用是比较频繁的,所有就来看看RecyclerView在dataBinding中是如何绑定数据的;

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:tools="http://schemas.android.com/tools"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <variable
                name="controllrecyclerview"
                type="com.lsm.databindingtest.RecyclerViewActivity.ControllRecyclerView"/>
        </data>
        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <Button
                android:id="@+id/btn_add"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="增加"
                tools:ignore="MissingConstraints"
                android:onClick="@{controllrecyclerview.addItem}"/>
            <Button
                android:id="@+id/btn_remove"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="删除"
                tools:ignore="MissingConstraints"
                app:layout_constraintTop_toBottomOf="@+id/btn_add"
                android:onClick="@{controllrecyclerview::removeItem}"/>
            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                tools:ignore="MissingConstraints"
                app:layout_constraintTop_toBottomOf="@+id/btn_remove">
            </android.support.v7.widget.RecyclerView>
        </android.support.constraint.ConstraintLayout>
    </layout>
    

    布局中和之前的写法一样,看看它adapter的写法有什么不同;

    public class BindingViewHolder<T extends ViewDataBinding> extends RecyclerView.ViewHolder {
        private T mBinding;
        public BindingViewHolder(@NonNull T binding) {
            super(binding.getRoot());
            mBinding = binding;
        }
        public T getBinding() {
            return mBinding;
        }
    }
    

    这了ViewHolder弄一个单独的类,没有将其弄成adapter的内部类了,实例化的时和以前不同的时传入dataBinding对象而不是View对象,然后通过getRoot方法去获取View对象;

    public class EmployeeAdapter extends RecyclerView.Adapter<BindingViewHolder> {
        private LayoutInflater mLayoutInflater;
        private OnItemClickListener mListener;
        private List<Worker> mWorkList;
    
        public interface OnItemClickListener {
            void onItemClickListener(Worker worker);
        }
    
        public EmployeeAdapter(Context context) {
            this.mLayoutInflater = LayoutInflater.from(context);
            this.mWorkList = new ArrayList<>();
        }
    
        @NonNull
        @Override
        public BindingViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
            ViewDataBinding binding = DataBindingUtil.inflate(mLayoutInflater, R.layout.item_work_on, viewGroup, false);
            return new BindingViewHolder(binding);
        }
    
        @Override
        public void onBindViewHolder(@NonNull BindingViewHolder bindingViewHolder, int i) {
            final Worker item = mWorkList.get(i);
            ViewDataBinding binding = bindingViewHolder.getBinding();
            binding.setVariable(BR.item, item);
            binding.executePendingBindings();
            bindingViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mListener != null) {
                        mListener.onItemClickListener(item);
                    }
                }
            });
        }
        @Override
        public int getItemCount() {
            return mWorkList.size();
        }
    
        public void setOnItemClickListener(OnItemClickListener listener) {
            this.mListener = listener;
        }
    
        public void addAll(List<Worker> workers) {
            mWorkList.addAll(workers);
        }
    
        Random mRandom = new Random(System.currentTimeMillis());
    
        public void add(Worker worker) {
            int position = mRandom.nextInt(mWorkList.size() +1);
            mWorkList.add(position,worker);
            notifyItemInserted(mWorkList.size());
        }
    
        public void remove() {
            if (mWorkList.size() == 0) {
                return;
            }
            int position = mRandom.nextInt(mWorkList.size());
            mWorkList.remove(position);
            notifyItemRemoved(position);
        }
    }
    

    在onCreateViewHolder方法中通过DataBindingUtil.inflate加载视图布局,并创建ViewDataBinding实例对象;onBindViewHolder方法中就不用像之前那样通过获取控件,然后对控件进行赋值,直接通过ViewHolder获取到对应的ViewDataBinding,然后调用setVariable对视图进行赋值,点击事件这些也可以按照之前的方式实现;
    item_work_on.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:tools="http://schemas.android.com/tools"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <variable
                name="item"
                type="com.lsm.databindingtest.Worker"/>
        </data>
        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="50dp">
            <TextView
                android:id="@+id/id_first_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                tools:ignore="MissingConstraints"
                android:text="@{item.firstName}"
                app:layout_constraintBottom_toTopOf="parent"
                app:layout_constraintTop_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                android:layout_marginLeft="10dp"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                tools:ignore="MissingConstraints"
                android:text="@{item.lastName}"
                app:layout_constraintBottom_toTopOf="parent"
                app:layout_constraintTop_toBottomOf="parent"
                app:layout_constraintLeft_toRightOf="@+id/id_first_name"
                android:layout_marginLeft="30dp"/>
        </android.support.constraint.ConstraintLayout>
    </layout>
    
    public class RecyclerViewActivity extends AppCompatActivity {
        private ActivityRecyclerviewBinding binding;
        private EmployeeAdapter adapter;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = DataBindingUtil.setContentView(this, R.layout.activity_recyclerview);
            binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
    
            adapter = new EmployeeAdapter(this);
            binding.recyclerView.setAdapter(adapter);
            adapter.setOnItemClickListener(new EmployeeAdapter.OnItemClickListener() {
                @Override
                public void onItemClickListener(Worker worker) {
                    Toast.makeText(RecyclerViewActivity.this, worker.getFirstName() + "--" + worker.getLastName(), Toast.LENGTH_LONG).show();
                }
            });
            binding.setControllrecyclerview(new ControllRecyclerView());
            List<Worker> demoList = new ArrayList<>();
            for (int i = 0; i < 5; i++) {
                Worker worker = new Worker("Zhai", "Mark");
                demoList.add(worker);
            }
            adapter.addAll(demoList);
        }
    
        public class ControllRecyclerView {
            public void addItem(View view) {
                Worker worker = new Worker("1111", "11111");
                adapter.add(worker);
            }
    
            public void removeItem(View view) {
                adapter.remove();
            }
        }
    }
    

    activity中直接通过dataBinding获取RecyclerView实例,然后设置LayoutMananger和adapter;这样就实现了列表数据的绑定,对于ListView和GridView列表数据的绑定差不多;


    GIF.gif

    @BindingAdapter自定义属性

    要将后台返回的url图片链接通过ImageView显示在界面上,需要通过第三方图片加载库将其加载显示出来,在dataBinding中xml布局中ImageView并不能通过@{}的方式加载url链接,那怎么来实现图片加载呢?通过@BindingAdapter自定义属性的方式可以实现;

    public class DemoBindingAdapter {
        @BindingAdapter({"app:imageUrl","app:placeholder"})
        public static void loadImageFromUrl(ImageView view, String url, Drawable drawable){
            Glide.with(view.getContext())
                    .load(url)
                    .placeholder(drawable)
                    .into(view);
        }
    }
    
    

    定义一个loadImageFromUrl的静态方法,并给方法添加@BindingAdapter注解,在注解中声明一个imageUrl和placeholder,在xml中给imageUrl和placeholder进行赋值;

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
        <data>
            <variable
                name="employee"
                type="com.lsm.databindingtest.Employee" />
        </data>
        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <ImageView
                android:id="@+id/iv_a"
                android:layout_width="150dp"
                android:layout_height="150dp"
                app:imageUrl="@{employee.avatar}"
                app:placeholder="@{@drawable/default_avatar}"
                tools:ignore="MissingConstraints" />
    
            <ImageView
                android:id="@+id/iv_b"
                android:layout_width="150dp"
                android:layout_height="150dp"
                app:imageUrl="@{employee.avatar}"
                app:layout_constraintTop_toBottomOf="@+id/iv_a"
                app:placeholder="@{@drawable/default_avatar}"
                tools:ignore="MissingConstraints" />
        </android.support.constraint.ConstraintLayout>
    </layout>
    

    通过app:imageUrl和app:placeholder进行引用;

    public class ExpressionActivity extends AppCompatActivity {
        private ActivityExpressionBinding binding;
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding= DataBindingUtil.setContentView(this,R.layout.activity_expression);
            Employee employee=new Employee("111","3333");
            employee.setAvatar("http://img.tupianzj.com/uploads/allimg/160728/9-160HP91408.jpg");
            binding.setEmployee(employee);
        }
    }
    
    微信截图_20190420204325.png

    双向绑定

    双向绑定的意思就是将数据model的值显示到视图上面,model改变时自动更新视图,视图改变时自动更新model;在dataBinding中通过BaseObservable和@={}来实现,注意不是@{}(赋值),是@={}

    public class FormModel extends BaseObservable {
        private String userName;
        private String passWord;
    
        public FormModel() {
        }
    
        public FormModel(String userName, String passWord) {
            this.userName = userName;
            this.passWord = passWord;
        }
        @Bindable
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
            notifyPropertyChanged(BR.userName);
        }
        @Bindable
        public String getPassWord() {
            return passWord;
        }
    
        public void setPassWord(String passWord) {
            this.passWord = passWord;
            notifyPropertyChanged(BR.passWord);
        }
    }
    

    数据model的写法还是和BaseObservable视图自动更新写法一样的;

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:tools="http://schemas.android.com/tools"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <variable
                name="formmodel"
                type="com.lsm.databindingtest.FormModel"/>
            <variable
                name="commitFrom"
                type="com.lsm.databindingtest.TwoWayActivity.CommitFrom"/>
        </data>
        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <EditText
                android:id="@+id/et_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="请输入用户名"
                tools:ignore="MissingConstraints"
                android:inputType="textNoSuggestions"
                android:text="@={formmodel.userName}"/>
            <EditText
                android:id="@+id/et_pwd"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="请输入密码"
                tools:ignore="MissingConstraints"
                android:inputType="textNoSuggestions"
                android:text="@={formmodel.passWord}"
                app:layout_constraintTop_toBottomOf="@+id/et_name"/>
            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="提交"
                tools:ignore="MissingConstraints"
                app:layout_constraintTop_toBottomOf="@+id/et_pwd"
                android:onClick="@{commitFrom.commitFrom}"/>
    
        </android.support.constraint.ConstraintLayout>
    </layout>
    
    public class TwoWayActivity extends AppCompatActivity {
        private ActivityTwoWayBinding binding;
        private FormModel formmodel;
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding= DataBindingUtil.setContentView(this,R.layout.activity_two_way);
    
            formmodel=new FormModel("111","222");
            binding.setFormmodel(formmodel);
            binding.setCommitFrom(new CommitFrom());
            formmodel.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
                @Override
                public void onPropertyChanged(Observable sender, int propertyId) {
                    //监听发送改变
                }
            });
        }
        public class CommitFrom{
            public void commitFrom(View view){
                Toast.makeText(TwoWayActivity.this,formmodel.getUserName()+"----"+formmodel.getPassWord(),Toast.LENGTH_LONG).show();
            }
        }
    }
    

    在activity中还可以通过addOnPropertyChangedCallback来监听视图的改变;


    GIF.gif

    这样就实现了数据和视图的双向绑定,在点击提交的时候并没有做其他操作,就只是做了一个Toast提示;

    动画

    接下来看下动画的简单实现;

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <import type="android.view.View" />
            <variable
                name="persenter"
                type="com.lsm.databindingtest.AnimationActivity.Persenter" />
            <variable
                name="showImage"
                type="boolean" />
        </data>
        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ImageView
                android:id="@+id/iv"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:src="@drawable/default_avatar"
                android:visibility="@{showImage?View.VISIBLE:View.GONE}"
                tools:ignore="MissingConstraints" />
            <CheckBox
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onCheckedChanged="@{persenter.onCheckedChanged}"
                android:text="图片显示或者隐藏"
                tools:ignore="MissingConstraints"
                app:layout_constraintTop_toBottomOf="@+id/iv"/>
        </android.support.constraint.ConstraintLayout>
    </layout>
    

    需要注意:不管是不是动画的实现,如果在布局中通过三元运算符等操作运算符来控制视图的显示或者隐藏,需要在data节点标签中做引用;

    <import type="android.view.View" />
    
    public class AnimationActivity extends AppCompatActivity {
        private ActivityAnimationBinding binding;
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding= DataBindingUtil.setContentView(this,R.layout.activity_animation);
    
            binding.addOnRebindCallback(new OnRebindCallback() {
                @Override
                public boolean onPreBind(ViewDataBinding binding) {
                    ViewGroup viewGroup= (ViewGroup) binding.getRoot();
                    TransitionManager.beginDelayedTransition(viewGroup);
                    return true;
                }
            });
            binding.setPersenter(new Persenter());
        }
        public class Persenter{
            public void onCheckedChanged(View buttonView, boolean isChanged){
                binding.setShowImage(isChanged);
            }
        }
    }
    
    GIF.gif
    上面这些只是dataBinding的部分用法,更多的用法可以查阅更多的资料进行学习。
    源码

    相关文章

      网友评论

        本文标题:Android dataBinding 的绑定数据、列表、点击事

        本文链接:https://www.haomeiwen.com/subject/jyblgqtx.html