MVVM框架学习(一)---------DataBinding以及RecycleView中如何使用

一:序

从一开始,小菜鸟我从MVC到用轮子,再到学习MVP,最终发现网上好多人都说使用MVVM的感觉都不一样,
所以到最后我就试着学习一个MVVM,发现代码的整洁度确实不同凡响。
在此记录如何使用以及自己的一些感悟。

二:MVVM

基本介绍
Android 官方把他们设计的架构模式封装成了一系列类的集合,其核心思想为MVVM,基于此扩展成为Android系统量身定做的架构模式,名为: Architecture Components(架构组件)。

有什么优点
减少样板代码,消除代码冗余(比MVP代码体积小很多)
针对Android系统的特点,设计出更实用功能
更高级的业务分离方式
有什么缺点
数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
一个大的模块中model也会很大,虽然使用方便了也很容易保证了数据的一致性,当时长期持有,不释放内存就造成了花费更多的内存
数据双向绑定不利于代码重用。客户端开发最常用的重用是View,但是数据双向绑定技术,让你在一个View都绑定了一个model,不同模块的model都不同。那就不能简单重用View了。
主要分为四个组件类,今天先进行学习第一个DataBinding.
DataBinding
Lifecycle
LiveData
ViewModel

三:DataBinding

由上面的分析来讲,看到前端的同学肯定对双向绑定并不陌生,这在vue里面是一个十分重要的功能,用起来也十分的方便。而DataBinding也差不多实现了这样的一个功能,并且在代码中也不用长篇大论的findViewById了.
那就让我们直接近距离感受一下把。
build.gradle中开启功能

android {

dataBinding {
enabled = true
}
}

gradle.properties启动新的编译器

android.databinding.enableV2=true

(1)创建数据源Bean

public class User {
    public final String firstName;
    public final String lastName;
    public User(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    public void onSaveClick(View view){

        System.out.println("绑定监听器。");
    }

}

(二)在xml中,增加< layout >< data >标签声明.
要注意,所有的DataBinding的xml,最外层都必须用layout包裹,否则会出错!.

<?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"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable name="user" type="com.example.databinding.User"/>
    </data>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_weight="1"
        android:text="@{user.firstName}"
         />
</RelativeLayout>
</layout>

(三)在activity中使用。在当你创建了一个databinding类的布局文件后,会自动生成一个相对应的绑定类,命名规则为:驼峰化xml文件名 + Binding.java

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

有了bindding对象后,就说明你就有了布局文件了,可以直接使用里面的控件

binding.name.setBackgroundColor(Color.WHITE);

当然,我们不需要手动为每个控件赋值,只需要对bingding进行对象的设置就可以了。

User user = new User("Test", "User");
binding.setUser(user);

实现效果
在这里插入图片描述
四:在RecycleView中使用DatraBinding
创建一个BaseBean.

public interface  BaseMessage {
    final int TextMessage = 0;
    final int ImageMessage = 1;
    final int ButtonMessage =2;
    int getType();
}

创建两个Bean继承其之
TextMessageBean


public class TextMessageBean extends BaseObservable implements BaseMessage{
    String msgTime = "";
    String content = "";
       public ButtonMessageBean(String message){
        setContent(message);
    }
}

ButtonMessageBean

public class ButtonMessageBean extends BaseObservable implements BaseMessage{
    String msgTime = "";
    String content = "";
       public ButtonMessageBean(String message){
        setContent(message);
    }
}

创建Adapter,继承RecyclerView.Adapter<RecyclerView.ViewHolder>


//这个是返回创造ViewHolder
//一个适配器,ViewHolder里面返回的一个ViewDataBinding
//onCreateViewHolder可以根据传入不同的类型,去形成不同的ViewDataBinding-->有不同的item布局了。
//onBindViewHolder时需要根据不同的类型去设置不同的值即可。
public class jvvm_recycleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<BaseMessage> list = null;
    private Context context = null;
    private int gviewType;
    public jvvm_recycleAdapter(Context cont, List<BaseMessage> li) {
        this.list = li;
        this.context = cont;
    }


    @NonNull
    @Override
    //根据传入的不同List显示不同的DataBinding
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ViewDataBinding binding = null;
        System.out.println("啥玩意:"+viewType);
        gviewType = viewType;
        switch (viewType){
            case BaseMessage.TextMessage:
                binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.recycle_image_item,parent,false);
                break;
            case BaseMessage.ButtonMessage:
                binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),R.layout.recycler_button_item,parent,false);
                break;
        }
        return new MyViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        switch (gviewType){
            case BaseMessage.TextMessage:
                ((MyViewHolder)holder).getBinding().setVariable(BR.TextMessageBean,list.get(position));
                break;
            case BaseMessage.ButtonMessage:
                System.out.println("测试一下");
                ((MyViewHolder)holder).getBinding().setVariable(BR.ButtonMessageBean,list.get(position));
                break;
        }
        
        ((MyViewHolder)holder).getBinding().executePendingBindings();

    }

    @Override
    public int getItemCount() {
        return list.size();
    }
    @Override
    public int getItemViewType(int position) {
        return list.get(position).getType();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{
        ViewDataBinding binding = null;
        public MyViewHolder(ViewDataBinding itemView) {
            super(itemView.getRoot());
            this.binding = itemView;
        }

        public ViewDataBinding getBinding(){
            return binding;
        }
    }

}

创建其总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"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable name="user" type="com.example.databinding.User"/>
    </data>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_weight="1"
        android:text="@{user.firstName}"
         />

    <androidx.recyclerview.widget.RecyclerView
        android:layout_below="@id/text"
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_weight="1">
    </androidx.recyclerview.widget.RecyclerView>


</RelativeLayout>
</layout>

其中的子item布局

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="TextMessageBean" type="com.example.databinding.TextMessageBean"/>

    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@{TextMessageBean.content}"
            />


    </RelativeLayout>
</layout>

子item布局

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="ButtonMessageBean" type="com.example.databinding.ButtonMessageBean"/>

    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/Button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@{ButtonMessageBean.content}"
            android:textColor="@color/red"
            />


    </RelativeLayout>
</layout>

Activitry中使用

public class jvvm extends AppCompatActivity {
    private static jvvm_recycleAdapter adapter;

    private static RecyclerView recyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityJvvmBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_jvvm);
        User user = new User("Test", "User");
        binding.setUser(user);
        //通过bindding获得test
        recyclerView = binding.recyclerview;
        adapter = new jvvm_recycleAdapter(this, initData());
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
    }

    public List<BaseMessage> initData() {
        List<BaseMessage> list = new ArrayList<>();
        list.add(new TextMessageBean("新消息一"));
        list.add(new TextMessageBean("新消息二"));
        list.add(new TextMessageBean("新消息三"));
        list.add(new TextMessageBean("新消息四"));
        list.add(new TextMessageBean("新消息五"));
        list.add(new TextMessageBean("新消息六"));
        list.add(new ButtonMessageBean("ppppppppppp"));
        list.add(new ButtonMessageBean("xxxxxxxxxxx"));

        return list;
    }
}

代码全部给出,重点在于适配器Adapter,可以看到,在初始化根据传入的不同的Bean,在OnCreateViewHolder方法内,会根据不同的type,去创建返回带不同布局的binding的Holder.不同的type是根据getItemViewType方法获得的
在onBindViewHolder中,也是根据不同的type,根据((MyViewHolder)holder).getBinding().setVariable(x,y)
去设置了不同的值。
这样实现了一个Recycleview的不同item的效果。
效果图如下.
在这里插入图片描述

五:总结

可能,各位还没有意识到其中发生的一些神奇的事情,使用DataBinding最让人舒服的点在于,去设置控件大小,而且设置点击事件的话,直接在Modle层就可以设置,只需要在xml中进行一个数据源的绑定即可。这样自然就省了很多代码量以及想如何设置的问题。
另外绑定监听设备,也是可以直接写到Model中去的,所以配置我们从拿到对象一步一步对控件的设置,就转变到了,如何设置数据源的问题上了~
当然,你说findByid可以用ButterKnife代替,但是这两个是不同的概念喔~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值