• 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中更新数据

  • 相关阅读:
    vue项目常用
    centos7之关于时间和日期以及时间同步的应用
    nginx 配置 https
    nginx 转发 minio 服务
    MSBUILD : error MSB3428: 未能加载 Visual C++ 组件“VCBuild.exe”。
    SpringCloud第三弹(Feign客户端)
    IDEA代码里的黄色提示
    H3C配置tftp参数,搭配WDS,windows部署服务器。
    手动为nextclou添加插件(Collabora Online 在线OFFICE)
    nextcloud集成LDAP登录
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/14108571.html
Copyright © 2020-2023  润新知