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

第一阶段:基础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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容