Android官方DataBinding(九):反向绑定,View变化结果回写进数据模型中

来源:互联网 发布:淘宝卖家发货软件 编辑:程序博客网 时间:2024/05/22 00:12
Android官方DataBinding(九):反向绑定,View变化结果回写进数据模型中

Android DataBinding Data Model数据模型的变化,引发View的变化,反过来,如果View的变化,也将导致数据模型(Data Model)的变化。本例给出一个例子,说明这一双向绑定过程。

附录文章大部分是单向绑定:数据模型的变化,引起View的变化。那么现在实行一个简单的功能,View的变化结果,回写到数据模型里面去。

写一个ViewModel类,里面定义一个布尔isDisplay:

package zhangphil.test;import android.databinding.BaseObservable;import android.databinding.ObservableBoolean;/** * Created by Phil on 2017/8/25. */public class ViewModel extends BaseObservable {    public final ObservableBoolean isDisplay = new ObservableBoolean();}


我以这样一个例子说明,在一个自定义View里面增加一个自定义属性:display,该值是布尔类型,如果true,则显示该View,如果false,则不显示该View。

自定义PhilView.java:

package zhangphil.test;import android.content.Context;import android.databinding.BindingAdapter;import android.databinding.InverseBindingAdapter;import android.databinding.InverseBindingListener;import android.util.AttributeSet;import android.util.Log;import android.view.View;/** * Created by Phil on 2017/8/25. */public class PhilView extends View {    private static final String TAG = "调试";    private OnViewChangeListener mOnViewChangeListener;    public PhilView(Context context, AttributeSet attrs) {        super(context, attrs);    }    //继承自Android,该方法在Android的View的visibility变化时候回调    @Override    protected void onVisibilityChanged(View changedView, int visibility) {        super.onVisibilityChanged(changedView, visibility);        Log.d(TAG, "onVisibilityChanged");        if (mOnViewChangeListener != null) {            mOnViewChangeListener.onChange();        }    }    @BindingAdapter(value = "display", requireAll = false)    public static void setDisplay(PhilView view, boolean isDisplay) {        if (getDisplay(view) == isDisplay) {            //防止死循环            Log.d(TAG, "重复设置");            return;        } else {            Log.d(TAG, "setDisplay " + isDisplay);            view.setVisibility(isDisplay ? View.VISIBLE : View.INVISIBLE);        }    }    @InverseBindingAdapter(attribute = "display", event = "displayAttrChanged")    public static boolean getDisplay(PhilView view) {        Log.d(TAG, "getDisplay:" + view.getVisibility());        return view.getVisibility() == View.VISIBLE;    }    @BindingAdapter(value = {"displayAttrChanged"}, requireAll = false)    public static void setDisplayAttrChanged(PhilView view, final InverseBindingListener inverseBindingListener) {        Log.d(TAG, "setDisplayAttrChanged");        if (inverseBindingListener == null) {            view.setViewChangeListener(null);            Log.d(TAG, "setViewChangeListener(null)");        } else {            view.setViewChangeListener(new OnViewChangeListener() {                @Override                public void onChange() {                    Log.d(TAG, "setDisplayAttrChanged -> onChange");                    inverseBindingListener.onChange();                }            });        }    }    private interface OnViewChangeListener {        void onChange();    }    private void setViewChangeListener(OnViewChangeListener listener) {        this.mOnViewChangeListener = listener;    }}


在activity_main.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>        <import type="android.view.View" />        <variable            name="model"            type="zhangphil.test.ViewModel" />    </data>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical">        <CheckBox            android:id="@+id/checkbox"            android:layout_width="50dp"            android:layout_height="50dp" />        <ImageView            android:layout_width="100dp"            android:layout_height="100dp"            android:src="@mipmap/ic_launcher_round"            android:visibility="@{checkbox.checked?View.VISIBLE:View.GONE}" />        <zhangphil.test.PhilView            android:id="@+id/philview"            android:layout_width="match_parent"            android:layout_height="200dp"            android:background="@android:color/holo_red_light"            app:display="@={model.isDisplay}" />    </LinearLayout></layout>



测试的MainActivity.java:

package zhangphil.test;import android.databinding.DataBindingUtil;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import zhangphil.test.databinding.ActivityMainBinding;public class MainActivity extends AppCompatActivity {    private final String TAG = "调试的MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        final ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);        final ViewModel vm = new ViewModel();        binding.setModel(vm);        //数据模型的变化将控制View的显示        vm.isDisplay.set(false);        Log.d(TAG, "数值变化:" + vm.isDisplay.get());        new Thread(new Runnable() {            @Override            public void run() {                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                runOnUiThread(new Runnable() {                    @Override                    public void run() {                        binding.philview.setVisibility(View.VISIBLE);                        //View的变化结果,值将回写到ViewModel的isDisplay中                        Log.d(TAG, "数值变化:" + vm.isDisplay.get());                    }                });            }        }).start();    }}



代码运行结果日志输出:

08-28 15:13:15.303 11275-11275/zhangphil.test D/调试的MainActivity: 数值变化:false08-28 15:13:15.335 11275-11275/zhangphil.test D/调试: setDisplayAttrChanged08-28 15:13:15.335 11275-11275/zhangphil.test D/调试: getDisplay:008-28 15:13:15.335 11275-11275/zhangphil.test D/调试: setDisplay false08-28 15:13:15.336 11275-11275/zhangphil.test D/调试: onVisibilityChanged08-28 15:13:15.336 11275-11275/zhangphil.test D/调试: setDisplayAttrChanged -> onChange08-28 15:13:15.336 11275-11275/zhangphil.test D/调试: getDisplay:408-28 15:13:18.310 11275-11275/zhangphil.test D/调试: onVisibilityChanged08-28 15:13:18.311 11275-11275/zhangphil.test D/调试: setDisplayAttrChanged -> onChange08-28 15:13:18.311 11275-11275/zhangphil.test D/调试: getDisplay:008-28 15:13:18.311 11275-11275/zhangphil.test D/调试的MainActivity: 数值变化:true08-28 15:13:18.319 11275-11275/zhangphil.test D/调试: getDisplay:008-28 15:13:18.319 11275-11275/zhangphil.test D/调试: 重复设置



附录:
1,《Android官方DataBinding简例(一)》链接:http://blog.csdn.net/zhangphil/article/details/77322530    
2,《Android官方DataBinding(二):动态数据更新notifyPropertyChanged》链接:http://blog.csdn.net/zhangphil/article/details/77328688   
3,《Android官方DataBinding(三):RecyclerView 使用ViewDataBinding更新数据》链接:http://blog.csdn.net/zhangphil/article/details/77367432  
4,《Android官方DataBinding(四):BindingAdapter》链接:http://blog.csdn.net/zhangphil/article/details/77374211 
5,《Android官方DataBinding(五):ObservableMap,ObservableArrayMap》链接:http://blog.csdn.net/zhangphil/article/details/77448933
6,《Android官方DataBinding(六): @= 操作符进行双向绑定》链接:http://blog.csdn.net/zhangphil/article/details/77454045 
7,《Android官方DataBinding(七):BindingMethods与BindingMethod》链接:http://blog.csdn.net/zhangphil/article/details/77479843 
8,《Android官方DataBinding(八):Lambda长表达式事件处理》链接:http://blog.csdn.net/zhangphil/article/details/77503013 

阅读全文
0 0