MVVM之DataBinding

参考自
Android官方数据绑定框架DataBinding(一)
Android官方数据绑定框架DataBinding(二)

  • 环境配置
    app模块的bulid.gradle下
    dataBinding{
        enabled=true;
    }

布局文件

  1. 以layout为根布局,并添加<data> 节点,这样layout里面就分为2部分,一部分就是data 一部分就是我们的布局。
  2. 在data里面绑定数据
<layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <import type="com.example.gzp.mvvmtest.Student"/>
            <variable
                name="stu"  
                type="student"/>
        </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:text="@{stu.name}"/>
        </LinearLayout>
</layout>

导入了一个student类 里面有name,add 属性 和相应的get,set方法。
或者type="com.example.gzp.mvvmtest.Student" 不用import。
type 支持基本数据类型和集合(list,map等)类型,类

<variable
    name="num"
    type="int" />
 <variable
    name="list"
    type="ArrayList&lt;String>"/>   

< 符号需要转义&lt;

       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{map[`name`]}"/>

集合变量名[key]的形式使用,如果你的key是一个字面字符串可以使用反引号,也可以使用转义后的双引号。
android:text='@{map["name"]}'
android:text="@{map[&quot;name&quot;]}"


  • 取别名

如果import了两个相同名称的类

    <import type="com.example.gzp.mvvmtest.Student" alisa="mystu"/>
    <import type="com.example.Student"/>
  • xml里还可以调用函数
    android:text="@{String.valueof(num)}"
  • 还可以调用表达式

    • Mathematical + - / * %
    • String concatenation +
    • Logical && ||
    • Binary & | ^
    • Unary + - ! ~
    • Shift >> >>> <<
    • Comparison == > < >= <=
    • instanceof
    • Grouping ()
    • Literals - character, String, numeric, null
    • Cast
    • Method calls
    • Field access
    • Array access []
    • Ternary operator ?:
  • 但是它不支持一下表达式:

    • this
    • super
    • new
    • Explicit generic invocation
  • ??表达式
    android:text='@{str ?? "null"}'
    等价于
    android:text='@{str!=null ? str:"null"}'

java

ActivityMainBinding binding=
DataBindingUtil.setContentView(this,R.layout.activity_main);

ActivityMainBinding 自动生成的类,命名方法:
将我们布局文件的首字母大写,并且去掉下划线,将下划线后面的字母大写,加上Binding组成。

  • 自定义类
    在xml文件中
    <data class=".Custom">
    …..
    </data>
    包名.Custom binding=DataBindingUtil.XXXXXX();
    给对应的变量赋值
    binding=setXXXX;
    XXX为我们在布局文件定义的变量首字母大写
    binding.setStr("string");
    binding.setList(arrayList);
  • 获取实例
    当我们需要某个view的实例时,我们只要给该view一个id,然后Data Binding框架就会给我们自动生成该view的实例
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{stu.name}"/>

mBinding.textView.setTextColor(Color.GREEN);
* 事件的绑定
……
<variable
name="handlers"
type="EventHandlers" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CLICK ME"
android:onClick="@{handlers.click}"/>
……

        binding.setHandler(new EventHandlers());

调用了EventHandlers里面的click(View view)方法。

  • 数据的同步
    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(包名.BR.name);
    }

在get方法上加上注释@Bindable
在set方法里面添加notifyPropertyChanged(包名.BR.name);

在点击事件中修改数据,数据就会自动修改了

    public void click(View view) {
        mStu.setName("ben");
    }
}
  • ObservableFields家族
    可以不需要定义get,set方法
    数据类型定义为:
    public ObservableField<String> name = new ObservableField<>();
    public ObservableInt age = new ObservableInt();
    Observable+基本数据类型的方式。

    • ObservableField
    • ObservableBoolean
    • ObservableByte
    • ObservableShort
    • ObservableInt
    • ObservableLong
    • ObservableDouble
    • ObservableParcelable
    • ObservableArrayMap
    • ObservableArrayList

    使用
    mPeople = new People();
    binding.setPeople(mPeople);
    mPeople.name.set("people");
    mPeople.age.set(19);
    mPeople.isMan.set(true);

......
     <variable
            name="str"
            type="android.databinding.ObservableField&lt;String>" />
     ......
        <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{str.get}"/>
ObservableArrayMap<String, String> map = new ObservableArrayMap<>();
ObservableArrayList<String> list = new ObservableArrayList<>();
map.put("name", "abc");
list.add("hi");
binding.setMap(map);
binding.setList(list);
  • 在fragment中使用

    infate方法
    MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
    MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);

     public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
            包名.Custom binding = DataBindingUtil.inflate(inflater,
                R.layout.frag_layout, container, false);
        mStu = new Student(20, "abc");
    //getRoot可以获取我们加载的布局
        return binding.getRoot();
    }
    
  • RecyclerView的使用
    private class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
        private ArrayList<Student> mData = new ArrayList<>();

        public MyAdapter(ArrayList<Student> data) {
            mData = data;
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //之前DataBindingUtil返回的那些都是ViewDataBinding的子类
            ViewDataBinding binding=DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.recycler_view_item, parent, false);
            //参数是item布局
            ViewHolder holder=new ViewHolder(binding.getRoot());
            //保存了刚刚返回的ViewDataBinding对象
            holder.setBinding(binding);
            return holder;
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            holder.getBinding().setVariable(BR.stu, mData.get(position));
            //当数据改变时,binding会在下一帧去改变数据,如果我们需要立即改变,就去调用executePendingBindings方法。
            holder.getBinding().executePendingBindings();
        }

        @Override
        public int getItemCount() {
            return mData.size();
        }


         class ViewHolder extends RecyclerView.ViewHolder{
            private ViewDataBinding mBinding;

            public ViewHolder(View itemView) {
                super(itemView);
            }

            public void setBinding(ViewDataBinding binding) {
                this.mBinding=binding;
            }

            public ViewDataBinding getBinding() {
                return  mBinding;
            }
        }
    }
}
  • 自定义setter
    • ImageView需要通过网络去加载图片
    • 格式化日期
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data class=".Custom">
        <variable
            name="imageUrl"
            type="String" />
        <variable
            name="time"
            type="java.util.Date" />
    </data>

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:image="@{imageUrl}"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{time}"/>
</layout>

java
binding.setImageUrl("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white_fe6da1ec.png");
binding.setTime(new Date());

public class Utils {
//BindingAdapter  参数是控件中使用的自定义属性名称(image)
    @BindingAdapter({"bind:image"})
    public static void imageLoader(ImageView imageView, String url) {
        Glide.with(imageView.getContext()).load(url).into(imageView);
    }
    //数据的转换
    @BindingConversion
    public static String convertDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(date);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值