Android中使用Adapter(適配器)給RecycleView設置數據源


場景

RecyclerView

RecyclerView是Android一個更強大的控件,其不僅可以實現和ListView同樣的效果,還有優化了ListView中的各種不足。其可以實現數據縱向滾動,也可以實現橫向滾動(ListView做不到橫向滾動)。

因為RecyclerView屬於新增的控件,Android將RecyclerView定義在support庫里。若要使用RecyclerView,第一步是要在build.gradle中添加對應的依賴庫。

Adapter適配器

顧名思義,就是把一些數據給弄得適當,適合以便於在View上顯示。可以看作是界面數據綁定的一種理解。它所操縱的數據一般都是一些比較復雜的數據,如數組,鏈表,數據庫,集合等。適配器就像顯示器,把復雜的東西按人可以接受的方式來展現。

數據源是各種各樣的,而ListView所展示數據的格式則是有一定的要求的。數據適配器正是建立了數據源與ListView之間的適配關系,將數據源轉換為ListView能夠顯示的數據格式,從而將數據的來源與數據的顯示進行解耦,降低程序的耦合性。這也體現了Android的適配器模式的使用

RecycleView是對ListView以及GridView的升級,在使用的時候同源更新需要使用Adapter適配器。但是RecycleView使用的適配器並不是之前的BaseAdapter了。RecycleView使用的適配器需要繼承RecyclerView.Adapter<VH extends RecycleView.ViewHolder>

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。

實現

創建RecyclerView

下面以一個示例入手看看怎樣使用一個Adapter給RecyclerView進行賦值。

首先新建一個項目,然后修改activity_main.xml的頁面布局如下

 

 

最終要實現的效果是點擊下面的imageView實現錄音,並將錄音文件的路徑顯示在上面的RecyclerView中。

關於錄音的實現不做講解,主要介紹錄音完成后使用Adapter給上面的RecyclerView添加數據源,這里以顯示錄音文件的路徑為例。

布局頁面activity_main.xml的代碼如下

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/layout_bottom"
        app:layout_constraintTop_toTopOf="parent" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="101dp"
        android:id="@+id/layout_bottom"
        android:background="#F7F7F7"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <ImageView
            android:layout_width="66dp"
            android:layout_height="66dp"
            android:id="@+id/img_voice"
            android:background="@mipmap/ic_launcher"
            android:layout_centerInParent="true"
            />

    </RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

注意上面添加RecyclerView的全路徑以及添加id屬性。

添加依賴

然后添加依賴。打開項目下的build.gradle,添加依賴

implementation 'com.android.support:recyclerview-v7:30.0.0'

 

注意這里的版本要與你上面的compileSdkVersion對應

 

 

創建item項的布局文件

然后為RecyclerView的item創建統一的布局文件,在layout下-New-XML-Layout XML File,這里命名為layout_chat_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_gravity="center"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/chat_item"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center" />

</LinearLayout>

 

你可以在這里任意設計視圖,它將會應用在你RecyclerView中每個項上。

這里為了演示,值簡單添加了一個TextView,記得給這個TextView設置ID

創建Adapter

我們在項目下新建一個包adapter,並在包下新建類ChatAdapter。

這個CharAdapter需要繼承RecycleView.Adapter<>,並且泛型里面的類型是自定義的繼承自RecycleView.ViewHolder的類。

關於ViewHolder

ViewHolder的主要任務:容納View視圖。Adapter連接了后端數據和前端顯示,viewHolder的作用就是提供前端的視圖文件。

這個自定義ViewHolder可以是外部類,但是為了方便,將其作為ChatAdaprer的內部類

需要在自定義的ViewHolder中綁定視圖文件,就好像在MainActivity中綁定activity_main.xml布局文件一樣

這里需要綁定我們在上面新建的每一項的布局視圖,即layout_chat_item.xml,並且獲取到每一項布局視圖的控件。

所以此時的ChatAdapter的代碼如下

public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ChatViewHolder> {

    class ChatViewHolder extends RecyclerView.ViewHolder{

        private TextView mText;

        public ChatViewHolder(View itemView) {
            super(itemView);
            mText = (TextView) itemView.findViewById(R.id.chat_item);
        }
    }
}

注意此時還沒有重寫指定的三個方法。

此時我們先創建一個數據實體類ChatBean

package com.badao.audiodemo.bean;

import androidx.annotation.NonNull;
import java.util.List;

public class ChatBean {
    
    private String msg;
    private int code;

    @NonNull
    private String id = "";
    
    private List<ChatItem> data;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public List<ChatItem> getData() {
        return data;
    }

    public void setData(List<ChatItem> data) {
        this.data = data;
    }

    @NonNull
    public String getId() {
        return id;
    }

    public void setId(@NonNull String id) {
        this.id = id;
    }


    public static class ChatItem {

        private int id;
        private String msgNum;
        private String content;
        //語音消息服務器地址
        private String remoteContent;
        private String sender;
        private String receiver;
        private String type;
        private boolean canReceived;
        private String sendTime;
        private String receivedTime;
        //語音時長
        private int voiceDuration;
        private boolean isRead;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getMsgNum() {
            return msgNum;
        }

        public void setMsgNum(String msgNum) {
            this.msgNum = msgNum;
        }

        public String getContent() {
            return content;
        }

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

        public String getSender() {
            return sender;
        }

        public void setSender(String sender) {
            this.sender = sender;
        }

        public String getReceiver() {
            return receiver;
        }

        public void setReceiver(String receiver) {
            this.receiver = receiver;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public boolean isCanReceived() {
            return canReceived;
        }

        public void setCanReceived(boolean canReceived) {
            this.canReceived = canReceived;
        }

        public String getSendTime() {
            return sendTime;
        }

        public void setSendTime(String sendTime) {
            this.sendTime = sendTime;
        }

        public String getReceivedTime() {
            return receivedTime;
        }

        public void setReceivedTime(String receivedTime) {
            this.receivedTime = receivedTime;
        }

        public int getVoiceDuration() {
            return voiceDuration;
        }

        public void setVoiceDuration(int voiceDuration) {
            this.voiceDuration = voiceDuration;
        }

        public String getRemoteContent() {
            return remoteContent;
        }

        public void setRemoteContent(String remoteContent) {
            this.remoteContent = remoteContent;
        }

        public boolean isRead() {
            return isRead;
        }

        public void setRead(boolean read) {
            isRead = read;
        }
    }

}

 

實體類的內容可以自己定義,這里是包含了語音消息實體的相關屬性。

然后再回到ChatAdapter,此時重寫其三個方法,然后新建上面實體的list作為數據源,並編寫其set方法

    private List<ChatBean.ChatItem> mEntityList = new ArrayList<>();


    public void setmEntityList(List<ChatBean.ChatItem> mEntityList) {
        this.mEntityList = mEntityList;
        //一定要記得加,否則視圖不會更新!!!
        notifyDataSetChanged();
    }

重寫onCreateViewHolder方法

返回我們的內部類MyViewHolder ,此處為將我們的item布局文件和adapter綁定。

    @NonNull
    @Override
    public ChatViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_chat_item, parent, false);
        return new ChatViewHolder(view);
    }

重寫onBindViewHolder方法

對每一項的TextView進行賦值,取出實體的某一屬性進行顯示,position為下標。

    @Override
    public void onBindViewHolder(@NonNull ChatViewHolder holder, int position) {
        holder.mText.setText(mEntityList.get(position).getContent().toString());
    }

重寫getItemCount方法

獲得實體list的長度,即顯示項的個數

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

此時完整的ChatAdapter的代碼為:

package com.badao.audiodemo.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.badao.audiodemo.R;
import com.badao.audiodemo.bean.ChatBean;

import java.util.ArrayList;
import java.util.List;

public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ChatViewHolder> {


    private List<ChatBean.ChatItem> mEntityList = new ArrayList<>();


    public void setmEntityList(List<ChatBean.ChatItem> mEntityList) {
        this.mEntityList = mEntityList;
        //一定要記得加,否則視圖不會更新!!!
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ChatViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_chat_item, parent, false);
        return new ChatViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ChatViewHolder holder, int position) {
        holder.mText.setText(mEntityList.get(position).getContent().toString());
    }

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

    class ChatViewHolder extends RecyclerView.ViewHolder{

        private TextView mText;

        public ChatViewHolder(View itemView) {
            super(itemView);
            mText = (TextView) itemView.findViewById(R.id.chat_item);
        }
    }
}

使用Adapter給RecycleView賦值

在MainActivity中先聲明所需對象

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private List<ChatBean.ChatItem> chatItemList;
    private  ChatAdapter chatAdapter;

然后在onCreate方法中初始化

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initRecyclerView();
    }

    /**
     * 初始化RecyclerView
     */
    private void initRecyclerView(){
        mRecyclerView = findViewById(R.id.recycler);
        chatItemList = new ArrayList<>();
        chatAdapter = new ChatAdapter();
        // 定義一個線性布局管理器
        LinearLayoutManager manager = new LinearLayoutManager(this);
        // 設置布局管理器
        mRecyclerView.setLayoutManager(manager);
        // 設置adapter
        mRecyclerView.setAdapter(chatAdapter);
    }

 

然后就是在需要對RecycleView進行賦值的地方,這里為例是在錄音結束后的回調方法中,也是在MainActivity中

        @Override
        public void onFinish(Uri uri, int i) {
            File file = new File(uri.getPath());
            ChatBean.ChatItem chatItem = new ChatBean.ChatItem();
            chatItem.setId((int) System.currentTimeMillis());
            chatItem.setSendTime(new Date().toString());
            chatItem.setContent(file.getAbsolutePath());

            chatItemList.add(chatItem);
            chatAdapter.setmEntityList(chatItemList);

        }

 

直接將實體類對象添加到list中並調用chatAdapter的set方法即可,就會自動在recycleView中更新數據

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM