美文网首页
学习路径:最基础ListView到 MVVM+DataBindi

学习路径:最基础ListView到 MVVM+DataBindi

作者: 小熊兜里有糖 | 来源:发表于2019-05-27 20:46 被阅读0次

    第一阶段:基础ListView的使用(包含重用和ViewHolder)

    • 首先是两个xml布局文件,由于极其简单,所以不做解释

      activity_main.xml

       <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="match_parent"
           android:layout_height="match_parent">
       
           <ListView
               android:id="@+id/list_view"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               />
       
       </LinearLayout>
      

      listview_item.xml

       <LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="horizontal">
       
           <TextView
               android:id="@+id/text1"
               android:layout_width="0dp"
               android:layout_height="wrap_content"
               android:layout_weight="1"/>
       
           <TextView
               android:id="@+id/text2"
               android:layout_width="0dp"
               android:layout_height="wrap_content"
               android:layout_weight="1"/>
       </LinearLayout>
      
    • 一般情况下,listView需要三个类例如

      • Fruit (用于封装item中的各个信息的类)
      • FruitAdapter (用于绑定xml中控件和item资源信息)
      • MainActivity (绑定Adapter和listView)

    ①MainActivity

        public class MainActivity extends AppCompatActivity {
            //用于存放listView资源信息
            ArrayList<Fruit> arrayList = new ArrayList<>();
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        
                ListView listView = findViewById(R.id.list_view);
                Fruit fruit1 = new Fruit("apple","abcde");
                Fruit fruit2 = new Fruit("banana","sadad");
                Fruit fruit3 = new Fruit("orange","fdgdf");
                arrayList.add(fruit1);
                arrayList.add(fruit2);
                arrayList.add(fruit3);
        
             //声明并绑定Adapter和listView
                FruitAdapter adapter = new FruitAdapter(this,R.layout.listview_item,arrayList);
                listView.setAdapter(adapter);
        
             //点击事件
                listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                        Fruit fruit = arrayList.get(i);
                        Toast.makeText(MainActivity.this,fruit.getName()+"被点击了",Toast.LENGTH_SHORT).show();
                    }
                });
        
            }
        }
    
     ②FruitAdapter最重要的类!!!
     
     - ViewHolder的使用结合了viewitem的回收机制,达到减少高消耗的findById的效果
     
     
            public class FruitAdapter extends ArrayAdapter {
        
                private int resourse;
            
                public FruitAdapter(Context context, int resource , List<Fruit> objects) {
                    super(context, resource,objects);
                    this.resourse = resource;
                }
            
                @Override
                public View getView(int position,  View convertView,ViewGroup parent) {
                    Fruit fruit = (Fruit) getItem(position);
                    ViewHolder viewHolder;
                    if (convertView == null){
                        convertView = LayoutInflater.from(getContext()).inflate(resourse,null);
                        viewHolder = new ViewHolder();
                        viewHolder.text1 = convertView.findViewById(R.id.text1);
                        viewHolder.text2 = convertView.findViewById(R.id.text2);
                        convertView.setTag(viewHolder);
            
                    }else {
                         viewHolder = (ViewHolder) convertView.getTag();
                    }
            
                    viewHolder.text1.setText(fruit.getName());
                    viewHolder.text2.setText(fruit.getDiscription());
            
                    return convertView;
                }
            
                class ViewHolder{
                    TextView text1;
                    TextView text2;
                }
            }
    

    Fruit

        public class Fruit {
        
            private String name ;
            private String discription;
        
            public Fruit(String name,String discription){
                this.name = name;
                this.discription = discription;
            }
        
            public String getName() {
                return name;
            }
        
            public String getDiscription() {
                return discription;
            }
        }
    

    第二阶段:listView结合DataBinding的使用

    • 什么是DataBinding?

            早在2015谷歌 I/O大会上,就介绍了一个新的框架DataBinding,从名字就可以看出
        来,这是一个数据绑定框架。我们为什么要使用DataBinding?
            1.再也不需要编写findViewById了,有人会说,已经有butterknife了,很好用。
            2.更新UI数据需切换至UI线程,也有人说,有rxjava了。
         但是DataBinding,不仅仅能解决这2个问题,它的核心优势在于,它解决了将数据分解映
         射到各个view的问题。什么个意思?具体来说,就是针对每个Activity或者Fragment的
         布局,在编译阶段,会生成一个ViewDataBinding类的对象,该对象持有Activity要展
         示的数据和布局中的各个view的引用。同时还有如下优势:将数据分解到各个view、在UI
         线程上更新数据、监控数据的变化,实时更新,这样一来,你要展示的数据已经和展示它的
         布局紧紧绑定在了一起。我认为这才是DataBinding真正的魅力所在。
      
    • 在build.gradle android模块中添加如下配置

        android {
             dataBinding {
                enabled = true
             }
        }
      
    • 创建一个JavaBean对象

        public class UserBean {
      
            private String name;
        
            private int age;
        
            public UserBean(String name , int age){
                this.name = name;
                this.age = age;
            }
        
            public int getAge() {
                return age;
            }
        
            public String getName() {
                return name;
            }
        }
      
    • xml文件

       这里和以前使用的xml不同,根节点变成了layout,里面包括了data节点和传统的布局。这里的data节点作用是连接 View 和 Modle 的桥梁。在这个data节点中声明一个variable变量,那值就可以轻松传到布局文件中来了。而且TextView中没有给控件定义id,而是在text的时候用了@{ }的方法,在括号里面直接引用UserBean对象的属性即可完成赋值。
      
      
            <layout xmlns:android="http://schemas.android.com/apk/res/android">
        
        
                <data>
                    <variable
                        name="user"
                        type="com.example.mvvmdeme.UserBean" />
                </data>
            
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@{user.name}"/>
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@{String.valueOf(user.age)}"/>
                </LinearLayout>
            
            </layout>
      
    • MainActivity

      这个activity很简洁,没有了控件的初始化的findViewById或者butterknife的那一堆注解(这个butterknife是啥意思我暂时还不知道),也没有了TextView的setText(),也就2行代码而已。大家应该已经看见了,这里用DataBindingUtil.setContentView代替了setContentView,然后创建一个 UserBean 对象,通过 binding.setUser(userBean) 与 variable 进行绑定。注意:这个ActivityMainBinding 是如何生成的呢?他是继承ViewDataBinding,这个类的生成是有规则的,它是根据对应的布局文件的名字生成的,可以直接使用的,比如:activity_main-->ActivityMainBinding 、fragment-->FragmentBinding即:第一个单词首字母大写,第二个单词首字母大写,最后都会拼上Binding就是生成的Binding类,

      <b>注意:在配置dataBinding = true之后生成的文件根节点才会是layout,所以之前生成的文件需要手动修改,只有根节点为layout的xml文件系统才会生成对应的Binding类。</b>

         public class MainActivity extends AppCompatActivity {
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                //系统生成的类
                ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
                UserBean bean = new UserBean("张三",25);
                binding.setUser(bean);
                //setContentView(R.layout.activity_main);
            }
        }
    

    第三阶段:RecyclerView的使用

    RecyclerView是什么?

    从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活。RecyclerView的官方定义如下:

        A flexible view for providing a limited window into a large data set.
    

    从定义可以看出,flexible(可扩展性)是RecyclerView的特点。
    RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,这一点从它的名字Recyclerview即回收view也可以看出。

    一些简单使用

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);  
    LinearLayoutManager layoutManager = new LinearLayoutManager(this );  
    //设置布局管理器  
    recyclerView.setLayoutManager(layoutManager);  
    //设置为垂直布局,这也是默认的  
    layoutManager.setOrientation(OrientationHelper. VERTICAL);  
    //设置Adapter  
    recyclerView.setAdapter(recycleAdapter);  
     //设置分隔线  
    recyclerView.addItemDecoration( new DividerGridItemDecoration(this ));  
    //设置增加或删除条目的动画  
    recyclerView.setItemAnimator( new DefaultItemAnimator());  
    

    简单使用

    • 在build.gradle文件中引入该类。

      在Android Gradle Plugin 3.0.0 以前,你可以使用以下进行配置

      compile 'com.android.support:recyclerview-v7:23.4.0'
      

      但是在3.0.0之后,弃用了compile,具体依赖配置项可以参阅官方文档

      https://developer.android.com/studio/build/dependencies?utm_source=android-studio#dependency_configurations
      

      3.0.0之后的依赖配置

      implementation 'com.android.support:recyclerview-v7:28.0.0'
      
    • 布局

    activity_main.xml

        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
            <android.support.v7.widget.RecyclerView
                android:id="@+id/RecycleView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
               />
        
        </LinearLayout>
    

    item_1.xml

        <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    
            <TextView
                android:id="@+id/text1"
                android:layout_width="0dp"
                android:layout_height="120dp"
                android:layout_weight="1"
                android:textAlignment="center"
                android:gravity="center"/>
        
            <TextView
                android:id="@+id/text2"
                android:layout_width="0dp"
                android:layout_height="120dp"
                android:layout_weight="1"
                android:textAlignment="center"
                android:gravity="center"/>
        
        </LinearLayout>
    
    • 同样是来一个JavaBean文件

        public class Fruit {
            private String name;
            private String description;
        
            public Fruit(String name,String description){
                this.name = name;
                this.description = description;
            }
        
            public String getName() {
                return name;
            }
        
            public String getDescription() {
                return description;
            }
        }
      
    • 最重要的一个适配器类,以RecycleviewAdapter为例

      适配器类需要继承自RecyclerView.Adapter<VH>,VH为你的ViewHolder的类名

        public class RecyclerviewAdapter extends RecyclerView.Adapter <RecyclerviewAdapter.ViewHolder> {
        
            List<Fruit> list;
        
            public RecyclerviewAdapter(List<Fruit> list){
                this.list = list;
            }
        
            @NonNull
            @Override
            public RecyclerviewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
                View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_1, viewGroup, false);
                return new ViewHolder(v);
            }
        
            @Override
            public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
                final int position = i;
                viewHolder.textView1.setText(list.get(position).getName());
                viewHolder.textView2.setText(list.get(position).getDescription());
        //        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        //            @Override
        //            public void onClick(View view) {
        //                Log.d("com.", "onClick: "+list.get(position).getName());
        //            }
        //        });
        
            }
        
        
            @Override
            public int getItemCount() {
                return list.size();
            }
        
            public static class ViewHolder extends RecyclerView.ViewHolder{
        
                private TextView textView1;
                private TextView textView2;
        
                public ViewHolder(@NonNull View itemView) {
                    super(itemView);
                    textView1 = itemView.findViewById(R.id.text1);
                    textView2  = itemView.findViewById(R.id.text2);
                }
           }
        }
      
    • MainActivity

        public class MainActivity extends AppCompatActivity {
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        
                RecyclerView recyclerView = findViewById(R.id.RecycleView);
                List<Fruit> list = initData();
                recyclerView.setLayoutManager(new LinearLayoutManager(this));
                recyclerView.setAdapter(new RecyclerviewAdapter(list));
                //添加分割线
                recyclerView.addItemDecoration(new DividerItemDecoration(this,1));
        
            }
        
            private List<Fruit> initData(){
        
                List<Fruit> list = new ArrayList<>();
        
                Fruit fruit1 = new Fruit("apple","first");
                Fruit fruit2 = new Fruit("orange","second");
                Fruit fruit3 = new Fruit("pear","third");
                Fruit fruit4 = new Fruit("banana","firth");
                Fruit fruit5 = new Fruit("saf","fifth");
                Fruit fruit6 = new Fruit("dsfsd","sixth");
                Fruit fruit7 = new Fruit("nbm","seventh");
        
                list.add(fruit1);
                list.add(fruit2);
                list.add(fruit3);
                list.add(fruit4);
                list.add(fruit5);
                list.add(fruit6);
                list.add(fruit7);
        
                return list;
            }
        }
      

    其他更详细可以参考博客,我觉得写的挺全的

     https://www.jianshu.com/p/4f9591291365
    

    阶段四:在RecyclerView中使用DataBinding

    本阶段是在RecyclerView中使用DataBinding,所以两者结合的时候,Adapter中方法略有不不同,个人理解是要将ViewHolder和DataBinding结合,所以方法有所差异

    • 整体结构可以看成四项
      • Activity
      • Adapter
      • BaseAdapter(帮助我们有效管理Adapter)
      • JavaBean

    先来看一下最重要的Adapter

    基类(用于管理的父类):

        public abstract class BaseBindRecyclerViewAdapter<T> extends RecyclerView.Adapter {
        
            public List<Fruit> mList; //数据源
            
            //这个inflater我个人感觉是用于提供子类进行xml绑定时需要的参数,所以在父类中统一实现声明
            public LayoutInflater inflater;
        
            public BaseBindRecyclerViewAdapter(Context context, List<Fruit> mList) {
                this.mList = mList;
                inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            }
        
            @Override
            public int getItemCount() {
                return mList.size();
            }
        
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                return onCreateMyViewHolder(parent,viewType);
            }
        
            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
                onBindMyViewHolder(holder, position);
            }
        
            //获取Item布局
            public abstract RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType);
        
            //绑定数据
            public abstract void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position);
        }
    

    再来看看具体实现的子类,此处以RecyclerviewAdapter.java为例

        public class RecyclerviewAdapter extends BaseBindRecyclerViewAdapter<RecyclerviewAdapter.ViewHolder> {
        
            //数据集
            List<Fruit> list;
        
            public RecyclerviewAdapter(Context context,List<Fruit> list){
                super(context,list);
                this.list = list;
            }
        
            //这个方法有所不同,绑定xml的方式转为用Binding进行绑定,然后把binding当做参数用于返回一个ViewHolder
            @Override
            public RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType) {
                Item1Binding binding = DataBindingUtil.inflate(inflater,R.layout.item_1,parent,false);
                return new ViewHolder(binding);
            }
        
            //这个方法也不一样,设置Bean的方式改为在binding中设置
            @Override
            public void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position) {
                Fruit fruitBean =  list.get(position);
                ((ViewHolder) holder).getBinding().setFruit(fruitBean);
                ((ViewHolder) holder).getBinding().executePendingBindings(); //解决databinding闪烁问题
        
            }
        
                
            @Override
            public int getItemCount() {
                return list.size();
            }
        
            //ViewHolder类有不同,不在进行繁琐的findById的绑定,绑定工作由DataBinding进行,DataBinding作为ViewHolder的参数。
            public static class ViewHolder extends RecyclerView.ViewHolder{
        
                private Item1Binding binding;
        
                public Item1Binding getBinding() {
                    return binding;
                }
        
                public ViewHolder(Item1Binding binding) {
                    super(binding.getRoot());
        
                    this.binding = binding;
                }
            }
        }
    

    MainActivity

        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //改为DataBinding绑定xml的方式
            ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
    
            List<Fruit> list = initData();
            //以下设置项唯一差别就是不是直接在RecyclerView设置,而是转为在binding下的RecycleView中设置。
            binding.RecycleView.setLayoutManager(new LinearLayoutManager(this));
            binding.RecycleView.setAdapter(new RecyclerviewAdapter(this,list));
            binding.RecycleView.addItemDecoration(new DividerItemDecoration(this,1));
    
        }
    

    xml以及Bean和以上DataBing代码中一样。

    阶段五:使用MVVM架构+DataBinding实现RecyclerView

    既然提到了MVVM就不得不总结一下android三个框架:MVC,MVP,MVVM

    • MVC

      • 视图层(View)

        对应于xml布局文件

      • 控制层(Controller)

        Android的控制层是由Activity来承担的,Activity本来主要是作为初始化页面,展示数据的操作,但是因为XML视图功能太弱,所以Activity既要负责视图的显示又要加入控制逻辑,承担的功能过多,在复杂一点的页面Activity代码量达到1000+也就不足为奇了。

      • 模型层(Model)

        我们针对业务模型,建立的数据结构和相关的类,它主要负责网络请求,数据库处理,I/O的操作。

    • MVP

      在Android开发中,Activity并不是一个标准的MVC模式中的Controller,本来它的首要职责是加载应用的布局和初始化用户界面,接受并处理来自用户的操作请求,进而作出响应。在MVC模式下随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。

      • 视图层(View)

        负责绘制UI元素、与用户进行交互,对应于xml、Activity、Fragment、Adapter

      • 模型层(Model)

        负责存储、检索、操纵数据,一般包含网络请求,数据库处理,I/O流。

      • 控制层(Presenter)

        Presenter是整个MVP体系的控制中心,作为View与Model交互的中间纽带,处理View于Model间的交互和业务逻辑。

      从去年到现在,MVP的设计思想在项目中用得比较多,它的具体实现就是接收到View的请求,从Model层获取数据,将数据进行处理,通过View层的接口回调给Activity或者Fragment。MVP能够让Activity成为真正的View,只做UI相关的事。它的优点还是很多的,不然也不会有这么多人喜欢它的,

    • 优点如下:

      • 1、模型与视图完全分离,我们可以修改视图而不影响模型;

      • 2、项目代码结构(文件夹)清晰,一看就知道什么类干什么事情;

      • 3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁

      • 4、协同工作(例如在设计师没出图之前可以先写一些业务逻辑代码或者其他人接手代码改起来比较容易)

    • 尽管这样,MVP模式也有不足之处,不然也不会推出MVVM了,缺点如下:

      • Presente层与View层是通过接口进行交互的,View层可能会有大量的接口,因为有可能好几个Activity都是去实现同一个View接口,那么所有用到的Activity都要去实现所有的方法(不管你是否用到),而且如果后面有些方法要删改,Presenter和Activity都要改动,比较麻烦;

      • MVP把Activity相当的一部分责任放到了Presenter来处理,复杂的业务同时也可能会导致P层太大,一旦业务逻辑越来越多,View定义的方法越来越多,会造成Activity和Fragment实现的方法越来越多,依然臃肿。

    • MVVM

      • Model :负责数据实现和逻辑处理,类似MVP。

      • View : 对应于Activity和XML,负责View的绘制以及与用户交互,类似MVP。

      • ViewModel : 创建关联,将model和view绑定起来,如此之后,我们model的更改,通过 viewmodel反馈给view,从而自动刷新界面。

    • 对于各个架构要更详细了解可以参考博客:

         https://www.jianshu.com/p/4830912f5162
      

      实战

    我自己又敲了一个思路清晰的简易版MVVM Demo,助于了解MVVM项目结构。(以下言论基于自己理解)
    首先MVVM项目分为几个部分:(但是我分成了6个类比不代表只需要6个java就完事了!)

    • View
      Activity、xml、Fragment等等

    • Model

    • ViewModal

    • Adapter

    • implement

    • JavaBean

    先来总结一下我在敲代码过程中体会到的每个角色的作用

    • View-如MainActivity

      这部分主要是编写界面,可以进行一些和数据无关的UI的修改和设计

      实例化Bing,绑定xml

      实例化Adapter

      实例化ViewModel(需要时把自身注入作为ViewModel的参数)

      实现一些响应或者操作,具体实现调用ViewModel实现(所以需要声明一个接口用来规范ViewModel)

    • Model (用于加载新数据)- 继承自一个Model的专用的接口来实现所需方法

    • ViewModel (绑定来自Model的数据和Adapter) - 继承自一个ViewModel的专用的接口来实现所需方法

      这个VM参数相对来说就比较多,需要在构造时传入Adapter用于数据更新,需要Model的实例化,在ViewModel实现的方法需要Model的参与,把自身作为响应者注入Model,然后Model数据变化后调用响应者的其他方法进行实现。

    • Adapter

      Adapter的作用没有大差异,还是用来管理itemView的绑定和数据绑定,提供给ViewModel用于相应数据变化的接口。

    上代码

    Bean代码和从前一样就不记录了

    • MainActivity

         public class MainActivity extends AppCompatActivity implements View.OnClickListener {
         
             ViewModel viewModel ;
         
             @Override
             protected void onCreate(Bundle savedInstanceState) {
                 super.onCreate(savedInstanceState);
                 //setContentView(R.layout.activity_main);
                 ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
                 //RecyclerView recyclerView = findViewById(R.id.RecycleView);
                 List<Fruit> list = initData();
                 RecyclerviewAdapter adapter =new RecyclerviewAdapter(this,list);
         
                 viewModel = new ViewModel(this,list,adapter);
         
                 binding.RecycleView.setLayoutManager(new LinearLayoutManager(this));
                 binding.RecycleView.setAdapter(adapter);
                 binding.RecycleView.addItemDecoration(new DividerItemDecoration(this,1));
         
             //!!!这里不可以写成binding.btn.OnClickListener(this);写成这样无效
                 binding.setClick(this);
         
             }
         
         //其实这部分不应该写在这里,但是偷个懒,写一下初始数据
             private List<Fruit> initData(){
         
                 List<Fruit> list = new ArrayList<>();
         
                 Fruit fruit1 = new Fruit("apple","first");
                 Fruit fruit2 = new Fruit("orange","second");
                 Fruit fruit3 = new Fruit("pear","third");
                 Fruit fruit4 = new Fruit("banana","firth");
                 Fruit fruit5 = new Fruit("saf","fifth");
                 Fruit fruit6 = new Fruit("dsfsd","sixth");
                 Fruit fruit7 = new Fruit("nbm","seventh");
         
                 list.add(fruit1);
                 list.add(fruit2);
                 list.add(fruit3);
                 list.add(fruit4);
                 list.add(fruit5);
                 list.add(fruit6);
                 list.add(fruit7);
         
                 return list;
             }
         
             @Override
             public void onClick(View view) {
                 switch (view.getId()){
                     case R.id.btn:
                         Log.d("com.example.mvvm", "onClick: 点击了");
                         //通过ViewModel实现具体逻辑
                         viewModel.ToRefresh();
                     default:
                         Log.d("com.example.mvvm", "onClick: 点击了");
         
         
                 }
           }
         }
      
    • Adapter:

      BaseBindRecyclerViewAdapter

          public abstract class BaseBindRecyclerViewAdapter<T> extends RecyclerView.Adapter {
      
              public List<Fruit> mList; //数据源
              public LayoutInflater inflater;
          
              public BaseBindRecyclerViewAdapter(Context context, List<Fruit> mList) {
                  this.mList = mList;
                  
                  //这个是为了子类绑定xml文件传参使用,上面也提到了
                  inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
              }
          
              @Override
              public int getItemCount() {
                  return mList.size();
              }
          
              @Override
              public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                  return onCreateMyViewHolder(parent,viewType);
              }
          
              @Override
              public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
                  onBindMyViewHolder(holder, position);
              }
          
              //获取Item布局
              public abstract RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType);
          
              //绑定数据
              public abstract void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position);
          
             //这个方法就是用于相应数据变化的,最好是把这个方法写进接口里
              public void addData(List<Fruit> list){
                  this.mList.addAll(list);
                  //一定要调用这个方法不然数据不会更新
                  notifyDataSetChanged();
              }
      
           }
      

      子类RecyclerviewAdapter

          public class RecyclerviewAdapter extends BaseBindRecyclerViewAdapter<RecyclerviewAdapter.ViewHolder> {
          
              List<Fruit> list;
          
              public RecyclerviewAdapter(Context context,List<Fruit> list){
                  super(context,list);
                  this.list = list;
              }
          
              @Override
              public RecyclerView.ViewHolder onCreateMyViewHolder(ViewGroup parent, int viewType) {
                  Item1Binding binding = DataBindingUtil.inflate(inflater,R.layout.item_1,parent,false);
                  return new ViewHolder(binding);
              }
          
              @Override
              public void onBindMyViewHolder(RecyclerView.ViewHolder holder, int position) {
                  Fruit fruitBean =  list.get(position);
                  ((ViewHolder) holder).getBinding().setFruit(fruitBean);
                  ((ViewHolder) holder).getBinding().executePendingBindings(); //解决databinding闪烁问题
          
              }
          
          //这方法暂时用不到
          //    @Override
          //    public int getItemViewType(int position) {
          //        return list.get(position).getItemViewType();
          //    }
          
              @Override
              public int getItemCount() {
                  return list.size();
              }
          
              public static class ViewHolder extends RecyclerView.ViewHolder{
          
                  private Item1Binding binding;
          
                  public Item1Binding getBinding() {
                      return binding;
                  }
          
                  public ViewHolder(Item1Binding binding) {
                      super(binding.getRoot());
                      this.binding = binding;
                  }
             }
          }
      
    • Model接口

         public interface ModelImp {
             public void NewData(VMImp listener);
         }
      
    • Model

          public class Model implements ModelImp {
      
              List<Fruit> list;
          
              public Model(List<Fruit> list){
                  this.list = list;
              }
          
              //这个方式用于实现数据变化,把实现了VMImp接口的VM作为响应者注入,然后调用相应者的方法
              @Override
              public void NewData(VMImp listener) {
                  List<Fruit> list = new ArrayList<>();
          
                  Fruit fruit1 = new Fruit("NEW","first");
                  Fruit fruit2 = new Fruit("NEW","second");
                  Fruit fruit3 = new Fruit("NEW","third");
                  Fruit fruit4 = new Fruit("NEW","firth");
                  Fruit fruit5 = new Fruit("NEW","fifth");
                  Fruit fruit6 = new Fruit("NEW","sixth");
                  Fruit fruit7 = new Fruit("NEW","seventh");
          
                  list.add(fruit1);
                  list.add(fruit2);
                  list.add(fruit3);
                  list.add(fruit4);
                  list.add(fruit5);
                  list.add(fruit6);
                  list.add(fruit7);
          
                  listener.succeed(list);
          
              }
          }
      
    • ViewModel的接口

          public interface VMImp {
              //MainActivity调用
              public void ToRefresh();
              //用于Model回调
              public void succeed(List<Fruit> list);
          }
      
    • ViewModel

         public class ViewModel implements VMImp{
             private AppCompatActivity view;
             private Model model;
             private RecyclerviewAdapter adapter;
         
         
             public ViewModel(AppCompatActivity view, List<Fruit> list,RecyclerviewAdapter adapter){
                 model = new Model(list);
                 this.view = view;
                 this.adapter = adapter;
             }
         
             //MainActivity调用
           @Override
             public void ToRefresh() {
                 model.NewData(this);
         
             }
         
             //用于Model回调
             public void succeed(List<Fruit> list){
                 adapter.addData(list);
             }
         }
      
    • activity_main.xml

         <layout xmlns:android="http://schemas.android.com/apk/res/android">
             <data>
                     <variable
                         name="click"
                         type="android.view.View.OnClickListener" />
             </data>
             <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:orientation="vertical">
                     <Button
                         android:id="@+id/btn"
                         android:layout_width="match_parent"
                         android:layout_height="100dp"
                         android:text="更新"
                         android:onClick="@{click}"/>
                     <android.support.v7.widget.RecyclerView
                         android:id="@+id/RecycleView"
                         android:layout_width="match_parent"
                         android:layout_height="match_parent"
                         />
             </LinearLayout>
         </layout>
      
    • item_1.xml

           <layout  xmlns:android="http://schemas.android.com/apk/res/android">
               <data>
                   <variable
                       name="fruit"
                       type="com.example.recyclerviewwithdatabinding.Fruit" />
               </data>
           
               <LinearLayout
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:orientation="horizontal">
           
                   <TextView
                       android:layout_width="0dp"
                       android:layout_height="120dp"
                       android:layout_weight="1"
                       android:textAlignment="center"
                       android:gravity="center"
                       android:text="@{fruit.name}"/>
           
                   <TextView
                       android:layout_width="0dp"
                       android:layout_height="120dp"
                       android:layout_weight="1"
                       android:textAlignment="center"
                       android:gravity="center"
                       android:text="@{fruit.description}"/>
           
               </LinearLayout>
           
           </layout>
      

    可参考文档

        https://www.jianshu.com/p/4f9591291365
    

    相关文章

      网友评论

          本文标题:学习路径:最基础ListView到 MVVM+DataBindi

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