Android Studio 学习笔记(四):Adapter和RecyclerView说明
在现版本中,滚动控件有多种,而相比于ListView,GridView,RecyclerView的用途更广,因此将前两者作为Adapter适配器的引入,再对RecyclerView进行简单讲解。
MVC & Adapter
为了方便理解,这里介绍一下Android应用设计的基础,也就是MVC架构,如图。
控制器(Controller)- 可看作一个中间桥梁,响应来自View的用户交互,通过对View设定的事件逻辑修改Model,再回传实现View的数据刷新。
视图(View) - 用户看到的图形界面,由界面设计人员负责。
模型(Model) - 保存数据状态,其中由程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。
MVC架构:Model(数据)以Controller(控制器)设定的方式呈现在View(用户界面)中。
简而言之:Adapter在其中充当Controller(控制器)的角色,在其中设定每一个元素长什么样子,怎么排列各个元素的逻辑,再把包含代码逻辑的复杂数据按设定好的样式给View。其中自带的BaseAdapter用得最多。
常见用法是新建一个类继承自BaseAdapter,重写其中的方法并构造新的方法,结合ListView、GridView控件使用。ListView和GridView的用法相似,只是功能不同,下面以ListView为例共同进行讲解
ListView & GridView
ListView是一种用于垂直显示的列表控件,如果显示内容过多,则会出现垂直滚动条。样式可参考某宝上购物列表的样子。GridView是以网格的形式排列显示的控件,样式可以类比手机桌面图标的排列。
下面以ListView的Adapter适配器为例(新建类MyListAdapter.java文件源码部分),就以下几个方面进行代码说明:
- 重写的两个方法 getCount(),getView() getItemId(),getItem()保持默认
- getView()参数说明及原理
- setTag()和getTag()原理简述
public class MyListAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mLayoutInflater;
MyListAdapter(Context context) {
this.mContext = context;
mLayoutInflater = LayoutInflater.from(context);
//加载布局管理器
}
@Override
public int getCount() {
//返回值 定义列表Item个数,即列表长度
return 10;
}
@Override
public Object getItem(int position) {
//根据position返回对应Item
return null; }
@Override
public long getItemId(int position) {
//根据position返回对应Item的Id
return 0; }
static class ViewHolder {
//为了方便复用,Item中元素抽象出来,新建了一个静态类ViewHolder,
public ImageView imageView;
public TextView tvTitle, tvTime, tvContent; }
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//position 当前Item是界面中的第几个(从0计数)
//convertView 展示在界面上的Item
//parent convertView的父控件,这里指ListView
// 该方法将xml布局转换为view对象
// 通过控件重用减少内存占用,比如一共new convertView x 1000 ,一次性全加载完肯定不够用
//这段代码让滑出屏幕的convertView在新滑进来的Item中重新使用,只需修改各控件的值
//未显示的Item保存在构件Recycler里
ViewHolder holder = null;
if (convertView == null) {
//没有供复用的convertView,新建一个
convertView = mLayoutInflater.inflate(R.layout.layout_list_item, null);
holder=new ViewHolder();
holder.imageView = convertView.findViewById(R.id.iv);
holder.tvTitle=convertView.findViewById(R.id.tv_title);
holder.tvTime=convertView.findViewById(R.id.tv_time);
holder.tvContent=convertView.findViewById(R.id.tv_content);
convertView.setTag(holder);
//Tag不像ID是用标示view的。Tag从本质上来讲是就是相关联的view的额外的信息。
//贴上一个标签,这个标签就是ViewHolder实例化后对象的一个属性,标示此时带有holder的convertView
//之后对于ViewHolder实例化的对象holder的操作,
//都会因为java的引用机制而一直存活并改变convertView的内容
}
else{
//有供复用的convertView,给控件重赋值,setText()自定义文本内容
holder= (ViewHolder) convertView.getTag();
取到此时带有holder的convertView
}
holder.tvTitle.setText("这是标题");
holder.tvTime.setText("2020-02-18");
holder.tvContent.setText("这是内容");
return convertView; }}
RecyclerView
官方定义为: A flexible view for providing a limited window into a large data set.
RecyclerView能够灵活展示大数据集,视图的复用管理比前两者(ListView、GridView)更好,通过加载不同的布局管理器(LayoutManager)可显示列表(LinerLayoutManager)、网格(GridLayoutManager)、瀑布流(StaggeredGridLayoutManager)等形式,且不同ViewHolder可实现item多元化的功能。标准化了ViewHolder,编写Adapter面向的是ViewHolder而不再是View,使得复用的逻辑被封装,写起来更加简单,而且直接省去了listview中convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
RecyclerView的四大组成是:
- Layout Manager:Item的布局。
- Adapter:为Item提供数据。
- Item Decoration:Item之间的划分样式Divider。
- Item Animator:添加、删除Item动画。
设计demo如下,采用LinearLayoutManager,和ListView效果相同,单数和双数采用不同的holder,实现了点击和长按事件
使用步骤(以列表视图为例)
首先需要在app/build.gradle中
引入包,版本自定
(androidx为
implementation 'androidx.recyclerview:recyclerview:1.0.0'
)或者导入design库,版本自定
(androidx为
implementation 'com.google.android.material:material:1.1.0-alpha09'
)分别设置Activity(LinearRecyclerViewActivity)和Item(layout_linear_item)的布局文件
指定布局管理器LayoutManager ,用于确定RecyclerView中Item的展示方式以及决定何时复用已经不可见的Item,避免重复创建以及执行高成本的findViewById()方法。
mRvMain.setLayoutManager(new LinearLayoutManager(LinearRecyclerViewActivity.this));
设置装饰样式
addItemDecoration可以允许应用给Adapter中来的View加特效和布局偏移,这对于在View间加分割线,高亮显示,可视化分组都很有用。
可以看作是给View加特技,一个个加的过程中如果加相同的特技,就起到分隔的作用;如果这几个加一种特技,另外几个加别的特技,就可以起到分组的作用;如果某几个加特技,就可以起到高亮的作用。mRvMain.addItemDecoration(new MyDecoration());
class MyDecoration extends RecyclerView.ItemDecoration{
//可重新定义以下三种方法中的任一种
public void onDraw(Canvas c, RecyclerView parent, State state)
//在Canvas上绘制内容,在绘制Item之前调用。
//(如果没有通过getItemOffsets设置偏移的话,Item的内容会将其覆盖)
public void onDrawOver(Canvas c, RecyclerView parent, State state)
//在Canvas上绘制内容,在Item之后调用。(画的内容会覆盖在Item的上层)
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)
//通过Rect为每个Item设置偏移,用于绘制Decoration。
}
RecyclerView的背景、onDraw绘制的内容、Item、onDrawOver绘制的内容,各层级关系如下:
指定适配器Adapter继承自RecyclerView.Adapter类
public class LinearAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
//也可创建静态内部类ViewHolder继承自RecyclerView.ViewHolder
RecyclerView将ListView中getView()的功能拆分成了
onCreateViewHolder()
和onBindViewHolder()
。实现3个方法
- onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
把View直接封装在ViewHolder中,负责每个Item的布局 - onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position)
主要用于适配渲染数据到View中,该方法使用ViewHolder而不是原来的convertView。 - getItemCount()
类似于BaseAdapter的getCount(),即定义总共有多少个Item。
- onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
长按事件的代码补充
天哥的视频演示中跳过了长按事件的代码,这里作下补充
LinearAdapter.java中
private OnItemLongClickListener mLongListener;
//新建私有变量用于保存监听器及set方法,这里的set方法统一放在下面的Adapter里了
public LinearAdapter(Context context, OnItemClickListener listener, OnItemLongClickListener Longlistener) {
...
this.mLongListener = Longlistener;
//相当于setOnItemLongClickListener()方法
}
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
...
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
//实现回调
@Override
public boolean onLongClick(View v) {
mLongListener.onLongClick(position);
Toast.makeText(mContext,"长按 pos:"+position,Toast.LENGTH_SHORT).show();
//另一种方法是在相应的Activity中设置Toast
return true;
//源码这里已经给出解释,如果返回值设为true,则系统消耗掉长按事件,这样就不会和点击事件冲突
}
});
}
public interface OnItemLongClickListener {
void onLongClick(int pos);//新建内部接口
}
另一种方法,上述代码中的Toast语句删去。
还需在LinearRecyclerViewActivity.java添加
mRvMain.setAdapter(new LinearAdapter(LinearRecyclerViewActivity.this, new LinearAdapter.OnItemClickListener() {...},
new LinearAdapter.OnItemLongClickListener(){
@Override
public void onLongClick(int pos) {
Toast.makeText(LinearRecyclerViewActivity.this,"longClick"+pos,Toast.LENGTH_SHORT).show();
}}));
参考资料
Android 常用控件及使用方法
Android Activity,Adapter基础讲解|菜鸟教程
https://www.runoob.com/android/android-acitivities.html
https://www.runoob.com/w3cnote/android-tutorial-adapter.html
Android与MVC设计模式
Android MVC 模式的介绍与实战
BaseAdapter中getView()里的3个参数是什么意思https://zhidao.baidu.com/question/1382059394224466060.html?qbl=relate_question_1&word=public View getView(int position%2C View convertView%2C ViewGroup parent)
对convertView的理解
convertView&setTag方法的一点理解
Android Adapter以及getView()方法的理解
Android 控件 RecyclerView
ItemDecoration学习
RecyclerView:打造悬浮效果
探究onCreateViewHolder和onBindViewHolder两者关系和调用次数
揭开RecyclerView的神秘面纱(二):处理RecyclerView的点击事件
Android开发视频教程最新版 Android Studio开发
Android Studio 学习笔记(四):Adapter和RecyclerView说明的更多相关文章
- Android Studio 学习笔记(一)环境搭建、文件目录等相关说明
Android Studio 学习笔记(一)环境搭建.文件目录等相关说明 引入 对APP开发而言,Android和iOS是两大主流开发平台,其中区别在于 Android用java语言,用Android ...
- Android Studio学习笔记
转:http://stormzhang.com/devtools/2014/11/25/android-studio-tutorial1 背景 相信大家对Android Studio已经不陌生了,An ...
- Android Studio 学习笔记(1)
最近从Eclipse转到Android Studio IDE,很多东西需要学习,本文是个记录. 项目结构 在Anroid Studio 中,一个Project 包括多个Module,每个Module下 ...
- Android Studio 学习笔记1.1 创建自己的第一个安卓项目并且打包APK
自从上一次安装完安卓开发工具Android Studio后抽时间看视屏尝试编写自己的第一个安卓项目约两周的时间 每天下班后会花上1~2小时的时间去学习 目前的成果如下:次元宅的我.apk 嘛 总而 ...
- Android Studio 学习笔记(三):简单控件及实例
控件.组件.插件概念区分 说到控件,就不得不区分一些概念. 控件(Control):编程中用到的部件 组件(Component):软件的组成部分 插件(plugin): 应用程序中已经预留接口的组件 ...
- Android Studio 学习笔记(二):布局简介和xmlns说明
初学Android Studio,是在b站看的教程视频,这里的笔记也是以其为基础的,个人强烈安利: [天哥]Android开发视频教程最新版 Android Studio开发 Android 布局简介 ...
- Android Studio 学习笔记(五):WebView 简单说明
Android中一个用于网页显示的控件,实际上,也可以看做一个功能最小化的浏览器,看起来类似于在微信中打开网页链接的页面.WebView主要用于在app应用中方便地访问远程网页或本地html资源.同时 ...
- Android Studio 学习(四) 数据库
文件存储 写数据 String data = "Data ti save"; FileOutputStream out =null; BufferedWriter writer = ...
- Git for Android Studio 学习笔记
http://learngitbranching.js.org/ 一个特别好的git学习教程 创建一个project,然后导入github
随机推荐
- 实验五:配置Eth-Trunk链路聚合(手工负载分担模式)
1.配置图 2.配置命令 LSW1的eth trunk 1配置如下: 配置命令如下: [S1]Eth-Trunk1 创建Eth-Trunk1端口 [S1-Eth-Trunk1]mode lacp-st ...
- Kdenlive-简单的操作
版权声明:原创文章,未经博主允许不得转载 前章:https://www.cnblogs.com/weilinfox/p/12246123.html 尽管是简单操作,但内容比较多.可以一边自己尝试编辑一 ...
- pc端的弹性布局适配方案
方案及原理:使用rem单位,通过window.onresize来监听浏览器窗口,获取窗口宽度,并改变跟字体大小来达到弹性适配效果. function adaptor(){ //为了便于计算,这里以19 ...
- 【Nginx入门系列】第三章 通过端口号区分虚拟主机
1.配置虚拟主机 (1)连接Nginx所在的服务器(我使用的是putty) (2)切换到nginx.conf 配置文件所在的目录,我目录是/usr/local/nginx/conf (3)增加一个虚拟 ...
- 前端入门nginx
一.nginx是什么 NGINX is a free, open-source, high-performance HTTP server and reverse proxy, as well as ...
- 一次DB故障引起的反思和MySQL Operator选型
前言 在一次数据库故障后,我们发现业务库会根据业务的等级会划分多个 MySQL 实例,许多业务库会同时属于一个 MySQL 实例,当一个库引发问题后整个实例的状态是不可控的.从而导致这个实例上的所有业 ...
- Android之SimpleAdapter简单实例和SimpleAdapter参数说明
SimpleAdapter基本上认知了其参数含义 用起来就简单多了 SimpleAdapter的参数说明 第一个参数 表示访问整个android应用程序接口,基本上所有的组件都需要 第二个参数表示生 ...
- List<E> 、Set<E>和Map<K,E>的简单应用
题目一: 创建两个线性表,分别存储{“chen”,“wang”,“liu”,“zhang”}和{“chen”,“hu”,“zhang”},求这两个线性表的交集和并集. 代码: List_Test.ja ...
- HDU_5057_分块
http://acm.hdu.edu.cn/showproblem.php?pid=5057 分块,保存每个块中每位对应数字的和,复杂的是getmum,左右下标所在的块不能直接读取block数组,要重 ...
- Educational Codeforces Round 39 Editorial B(Euclid算法,连续-=与%=的效率)
You have two variables a and b. Consider the following sequence of actions performed with these vari ...