1. 程式人生 > >關於Android的Databinding在RecyclerView上使用的記錄

關於Android的Databinding在RecyclerView上使用的記錄

       首先我是 不太喜歡Databinding這玩意的,雖然用著還是蠻爽的,一繫結所有的控制元件直接拿到,也不用findViewbyid了,但是這東西出錯誤了巨難差。你要是在xml裡面寫錯了,AndroidStudio不報錯的那種錯誤,那你就頭疼吧。Databinding物件死活就不會生成,糾結到死。 算了,不吐槽了,說不上AndroidStudio以後會對Databinding支援的特別好 也說不好。

       廢話不多說。這裡記錄一下在RecyclerView中使用Databinding,在多佈局的時候簡化佈局那還是挺爽的。Databinding的配置自己搞,網上一查一大堆。我預設你們都配置好了Databinding和Glide了。

完成樣式:

 第一步,我們先建立最基本的MainActivity和它的layout, 這裡主activity的layout用Databing純屬是我偷懶不想寫findViewById。哈哈哈

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static MessageAdapter adapter = null;
    private static RecyclerView recyclerView = null;
    private static ActivityMainBinding binding = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
        binding.addTextItem.setOnClickListener(this);
        binding.addImageItem.setOnClickListener(this);
        recyclerView = binding.recyclerview;

        adapter = new MessageAdapter(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 ImageMessageBean("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542465393611&di=677e365a4eb62a29278aef1d5d48fa40&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201411%2F11%2F20141111171817_8chGL.jpeg"));
        list.add(new TextMessageBean("新訊息五"));
        list.add(new TextMessageBean("新訊息六"));
        return list;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.add_text_item:
                adapter.updateItem(new TextMessageBean("新訊息到了~"));

                break;
            case R.id.add_image_item:
                adapter.updateItem(new ImageMessageBean("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542468020668&di=43a1083a4d0ae308f90403b34463ec8a&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201605%2F10%2F20160510170018_sKmZe.thumb.700_0.png"));
                break;
        }
        //這個是每次都滾動到最後一行
        recyclerView.scrollToPosition(adapter.getItemCount()-1);
    }

}
<?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>

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">

        </android.support.v7.widget.RecyclerView>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/add_text_item"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="增加文字訊息" />

            <Button
                android:id="@+id/add_image_item"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="增加圖片訊息" />
        </LinearLayout>

    </LinearLayout>
</layout>

第二步,我們建立一個BaseMessage的介面,讓兩個資料JavaBean都繼承它,分別存放文字型別和圖片型別,這玩意後期自己還能拓展拓展啥的。

BaseMessage

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

TextMessageBean

public class TextMessageBean extends BaseObservable implements BaseMessage{
    String msgTime = "";
    String content = "";

    public TextMessageBean(String message){
        setContent(message);
    }

    public String getMsgTime() {
        return msgTime;
    }

    public void setMsgTime(String msgTime) {
        this.msgTime = msgTime;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public int getType() {
        return BaseMessage.TextMessage;
    }
}

 ImageMessageBean(這裡面注意特殊寫了一個方法讓glide處理傳入URL設定圖片)

public class ImageMessageBean implements BaseMessage{
    String imageURL = "";

    public ImageMessageBean(String url){
        setImageURL(url);
    }

    public String getImageURL() {
        return imageURL;
    }

    public void setImageURL(String imageURL) {
        this.imageURL = imageURL;
    }

    @Override
    public int getType() {
        return BaseMessage.ImageMessage;
    }

    //這裡寫了一個static方法,用於特殊處理傳入的圖片
    //第一個引數是預設的繫結資料型別是什麼就會傳入
    //第二個引數是設定的引數
    @BindingAdapter({"loadImage"})
    public static void loadImage(ImageView imageView,String url){
        Glide.with(imageView).load(url).into(imageView);
    }


}

第三步,寫這個通用的Adapter方法。(Recycler使用就不科普了,來看的都會用 )

public class MessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<BaseMessage> list = null;
    private Context context = null;

    public MessageAdapter(Context cont,List<BaseMessage> li){
        this.list = li;
        this.context = cont;
    }
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        ViewDataBinding binding = null;
        switch (viewType){
            case BaseMessage.TextMessage:
                binding = DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()),R.layout.recycler_msg_item,viewGroup,false);
                break;
            case BaseMessage.ImageMessage:
                binding = DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()),R.layout.recycler_img_item,viewGroup,false);
                break;
        }
        return new MyViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {

        ((MyViewHolder)viewHolder).getBinding().setVariable(BR.data,list.get(position));
        ((MyViewHolder)viewHolder).getBinding().executePendingBindings();
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

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

    public void updateItem(BaseMessage message){
        list.add(message);
        notifyDataSetChanged();
    }

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

        public ViewDataBinding getBinding(){
            return binding;
        }
    }

}

這裡最方便的就是,多種資料型別你只需要寫一個ViewHolder,寫一個onBindViewHolder就可以處理了。你只需要在onCreateBindView中判斷一下資料型別構造不同的view就可以了。很屌很溜