DataBind 不写adapter和viewholder了

针对评论里问题的补充(补)DataBind 不写adapter和viewholder了

1、 项目gradle 引入databind支持

android{
...
    dataBinding {
        enabled = true
     }
...
    }
复制代码

2、databind 基本功能介绍

(抄的介绍。。。真多)

  1. 单纯的摆脱findviewbyid
  2. 绑定基本数据类型及String
  3. 绑定Model数据
  4. 绑定事件
  5. 通过静态方法转换数据类型
  6. 通过运算符操作数据
  7. 自定义Binding的类名
  8. 绑定相同Model的操作
  9. model变量改变自动更新数据
  10. 绑定List/Map等集合数据
  11. Observable自动更新
  12. Databinding与include标签的结合
  13. DataBinding与RecyclerView的结合

3、简单使用

a.创建一个类(这里用简单的实体类)

public class User {
    private String text;

    public User(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}
复制代码

b.创建一个布局 显示User的text属性

activity_main.xml
"1.0" encoding="utf-8"?>

    
        
    "http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        "@+id/main_btn3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.text}" />
            
    

复制代码

c、在布局中使用

public class MainActivity extends AppCompatActivity {
    //注意
    //注意
    //注意
    //注意
    //引入前  要makeProject 生成代码
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //通过DataBInding加载布局都会对应的生成一个对象,如ActivityMainBinding,对象名在布局文件名称后加上了一个后缀Binding
        binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);

        //绑定model对象数据
        User user = new User("绑定Model数据类型");
        binding.setUser(user);
        //或者 binding.setVariable(BR.user,user);
    }
    //运行就会发现TextView的text已经改变
}
复制代码

4、开始啦

a、算术入门啦 进入正题

//老规矩 先写布局  布局很简单 就一个textView 一个recycler
"1.0" encoding="utf-8"?>

"http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="lzf.one.adapter.MainActivity">

    "@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="9dp"
        android:text="点击显示recycler"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    "@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/text" />


复制代码

c、创建model 给上面布局使用

//实体类 给recycler的item用  为了方便 写的简单
public class UserInfo {
    private String name;
    private String age;

    public UserInfo(String name, String age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
//model 提供数据  提供一个userInfoList 没啥毛病
public class UserViewModel {
    private List userInfoList;

    public UserViewModel() {
        this.userInfoList = new ArrayList<>();
    }

    public List getUserInfoList(){
        userInfoList.add(new UserInfo("张三","25岁"));
        userInfoList.add(new UserInfo("张三","25岁"));
        userInfoList.add(new UserInfo("张三","25岁"));
        userInfoList.add(new UserInfo("张三","25岁"));
        return userInfoList;
    }
}

复制代码

d、数据准备好了 我们开始写啦

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding mBind;
    private UserViewModel userViewModel;
    private MyAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBind = DataBindingUtil.setContentView(this, R.layout.activity_main);
        mBind.text.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mBind.recycler.setVisibility(View.VISIBLE);
            }
        });
        mBind.recycler.setLayoutManager(new LinearLayoutManager(this));
        userViewModel=new UserViewModel();
        adapter=new MyAdapter(this,userViewModel.getUserInfoList());
        mBind.recycler.setAdapter(adapter);
    }
}
//接下来 我们开始写adapter  我们先正常写

public class MyAdapter extends RecyclerView.Adapter{
    private Context context;
    private List userInfoList;

    MyAdapter(Context context, List userInfoList) {
        this.context = context;
        this.userInfoList = userInfoList;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        UserItemBinding userItemBinding= DataBindingUtil.inflate(LayoutInflater.from(context),R.layout.user_item,parent,false);
        return new MyViewHolder(userItemBinding);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        UserItemBinding userItemBinding=holder.getUserItemBinding();
        userItemBinding.setUser(userInfoList.get(position));
        userItemBinding.executePendingBindings();
    }

    @Override
    public int getItemCount() {
        return userInfoList==null?0:userInfoList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{
        UserItemBinding userItemBinding;
        MyViewHolder(UserItemBinding userItemBinding) {
            super(userItemBinding.getRoot());
            this.userItemBinding=userItemBinding;
        }

        UserItemBinding getUserItemBinding() {
            return userItemBinding;
        }
    }
}
复制代码

e、开始优化

我们先来优化ViewHolder

   class MyViewHolder extends RecyclerView.ViewHolder{
        UserItemBinding userItemBinding;
        MyViewHolder(UserItemBinding userItemBinding) {
            super(userItemBinding.getRoot());
            this.userItemBinding=userItemBinding;
        }

        UserItemBinding getUserItemBinding() {
            return userItemBinding;
        }
    }
    UserItemBinding 继承 ViewDataBinding
    根据多态 那么 我们可以把viewholder里的UserItemBinding改成ViewDataBinding

    class MyViewHolder extends RecyclerView.ViewHolder{
        ViewDataBinding viewDataBinding;
        MyViewHolder(ViewDataBinding viewDataBinding) {
            super(viewDataBinding.getRoot());
            this.viewDataBinding=viewDataBinding;
        }

        ViewDataBinding getViewDataBinding() {
            return viewDataBinding;
        }
    }
    这样来看 viewholder就不再依赖一个具体的databinding而是依赖ViewDataBinding(父类)
    那么viewHolder现在是通用的了  我可以一直使用
    
复制代码

我们再来优化adapter 要adapter实现万能最起码的 要实现多类型item 关于 Android Adapter,你的实现方式可能一直都有问题 我们可以类似的实现 将Item的layoutId当作Itme的viewType。我们先来改造实体类UserInfo

//写个接口 定义一个规范
public interface BindAdapterType {
    int getType();
}
//userInfo实现接口
public class UserInfo implements BindAdapterType {
    private String name;
    private String age;

    public UserInfo(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
    //注意
    @Override
    public int getType() {
    //返回layoutId 当作userItem的viewType
        return R.layout.user_item;
    }
}
复制代码

那么 现在我们的adapter变成什么样了呢

public class MyAdapter extends RecyclerView.Adapter{
    private Context context;
    private List userInfoList;

    MyAdapter(Context context, List userInfoList) {
        this.context = context;
        this.userInfoList = userInfoList;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(DataBindingUtil.
                inflate(LayoutInflater.from(context),
                        viewType,parent,false));
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
    //这里编译过不去  别急  一点点改
        UserItemBinding userItemBinding=holder.getViewDataBinding();
        userItemBinding.setUser(userInfoList.get(position));
        userItemBinding.executePendingBindings();
    }

    @Override
    public int getItemCount() {
        return userInfoList==null?0:userInfoList.size();
    }

    @Override
    public int getItemViewType(int position) {
        return userInfoList.get(position).getType();
    }
}
复制代码

这时候 我们会看到onCreateViewHolder()不再依赖具体的layoutId啦,而是userInfo固有的属性Type,viewholder也是通用的了,那么我们的onCreateViewHolder()算是改造完成了 接着我们来改造onBindViewHolder()

//这里有个前置的知识
//对于每个中使用的变量名称 databind都会生成一个id
//举个例子
"http://schemas.android.com/apk/res-auto">

    

        "user"
            type="lzf.one.adapter.UserInfo" />
    

    "http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        //节省空间 里面的内容删掉了 就是user_item.xml
    

那么onBindViewHolder()我们就可以改造成这样
     @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.getViewDataBinding().setVariable(BR.user,userInfoList.get(position));
        holder.getViewDataBinding().executePendingBindings();
    }
    //在这里BR.user这个id是user_item.xml的user的资源id
    //user_item又引用了userInfo,我们是不是可以类似viewType的方式 把id当作userInfo的属性呢?
    //我们来试试
复制代码

改造接口

public interface BindAdapterType {
    int getType();
    int getId();
}
复制代码

userInfo 实现getId()方法

//get/set方法去掉 展示主要内容
public class UserInfo implements BindAdapterType {
    private String name;
    private String age;

    public UserInfo(String name, String age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int getType() {
        return R.layout.user_item;
    }

    @Override
    public int getId() {
        return BR.user;
    }
}
复制代码

那么现在onBindViewHolder()就变成什么样了呢?我们来看一下:

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.getViewDataBinding().setVariable(
        userInfoList.get(position).getId(),
        userInfoList.get(position));
        holder.getViewDataBinding().executePendingBindings();
    }
复制代码

到现在我们已经基本改造完成了 现在我们可以把List的泛型换掉了 他已经不再单纯的是userInfo 而是list data(userInfo 实现了接口BindAdapterType); 现在 我们已经改造成功了 我们来看看完整的代码

//现在adapter不再限定接受userInfo的集合了 而是任何实现了BingAdapterType接口的实体
//可以是userInfo 也可以是studentInfo
//只要实现了BindAdapterType接口就行(getType()、getId()的返回值还是要给的(0.0)
//至于item的交互 你就在对应的实体里面写呗
public class MyAdapter extends RecyclerView.Adapter{
    private Context context;
    private List userInfoList;

    MyAdapter(Context context, List userInfoList) {
        this.context = context;
        this.userInfoList = userInfoList;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(DataBindingUtil.
                inflate(LayoutInflater.from(context),
                        viewType,parent,false));
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.getViewDataBinding().setVariable(userInfoList.get(position).getId(),userInfoList.get(position));
        holder.getViewDataBinding().executePendingBindings();
    }

    @Override
    public int getItemCount() {
        return userInfoList==null?0:userInfoList.size();
    }

    @Override
    public int getItemViewType(int position) {
        return userInfoList.get(position).getType();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{
        ViewDataBinding viewDataBinding;
        MyViewHolder(ViewDataBinding viewDataBinding) {
            super(viewDataBinding.getRoot());
            this.viewDataBinding=viewDataBinding;
        }

        ViewDataBinding getViewDataBinding() {
            return viewDataBinding;
        }
    }
}
复制代码

代码地址

你可能感兴趣的:(DataBind 不写adapter和viewholder了)