DataBind 不寫adapter和viewholder了

針對評論裏問題的補充(補)DataBind 不寫adapter和viewholder了

一、 項目gradle 引入databind支持

android{
...
    dataBinding {
        enabled = true
     }
...
    }
複製代碼

二、databind 基本功能介紹

(抄的介紹。。。真多)android

  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的結合

三、簡單使用

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
<?xml version="1.0" encoding="utf-8"?><!--佈局以layout做爲根佈局-->
<layout>
    <data>
        <!--綁定Model
        name:
        user是User的一個實例的引用 相似於
        User user_ex=new User()
        這個user 等待activity/fragment或其餘地方進行注入
        type:
        User類的全路徑
        >
        <variable
            name="user"
            type="lzf.one.adapter.UserInfo" />

    </data>
    <!--咱們須要展現的佈局  熟悉的佈局吧-->
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/main_btn3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.text}" />
            <!--這裏user.text至關於user.getText()-->
    </LinearLayout>
</layout>
複製代碼

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已經改變
}
複製代碼

四、開始啦

image

a、算術入門啦 進入正題

//老規矩 先寫佈局  佈局很簡單 就一個textView 一個recycler
<?xml version="1.0" encoding="utf-8"?>
<layout>
<android.support.constraint.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="lzf.one.adapter.MainActivity">

    <TextView
        android:id="@+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" />

    <android.support.v7.widget.RecyclerView
        android:id="@+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" />
</android.support.constraint.ConstraintLayout>
</layout>
複製代碼

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<UserInfo> userInfoList;

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

    public List<UserInfo> 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<MyAdapter.MyViewHolder>{
    private Context context;
    private List<UserInfo> userInfoList;

    MyAdapter(Context context, List<UserInfo> 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、開始優化

咱們先來優化ViewHoldergit

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。咱們先來改造實體類UserInfogithub

//寫個接口 定義一個規範
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變成什麼樣了呢bash

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
    private Context context;
    private List<UserInfo> userInfoList;

    MyAdapter(Context context, List<UserInfo> 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()app

//這裏有個前置的知識
//對於每一個<layout></layout>中使用的變量名稱 databind都會生成一個id
//舉個例子
<layout xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
        //注意注意
        //對於user這個引用 databind會生成一個(int類型)BR.user的資源
            name="user"
            type="lzf.one.adapter.UserInfo" />
    </data>

    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        //節省空間 裏面的內容刪掉了 就是user_item.xml
    </android.support.constraint.ConstraintLayout>
</layout>
那麼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的屬性呢?
    //咱們來試試
複製代碼

改造接口ide

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()就變成什麼樣了呢?咱們來看一下:post

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

到如今咱們已經基本改造完成了 如今咱們能夠把List的泛型換掉了 他已經再也不單純的是userInfo 而是list<? extend BindAdapterType> data(userInfo 實現了接口BindAdapterType); 如今 咱們已經改形成功了 咱們來看看完整的代碼gradle

//如今adapter再也不限定接受userInfo的集合了 而是任何實現了BingAdapterType接口的實體
//能夠是userInfo 也能夠是studentInfo
//只要實現了BindAdapterType接口就行(getType()、getId()的返回值仍是要給的(0.0)
//至於item的交互 你就在對應的實體裏面寫唄
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
    private Context context;
    private List<? extends BindAdapterType> userInfoList;

    MyAdapter(Context context, List<? extends BindAdapterType> 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;
        }
    }
}
複製代碼

代碼地址優化

相關文章
相關標籤/搜索