android viewholder继承,Android RecyclerView中的ViewHolder
在使用android提供的组件以列表的格式显示数据时,使用过ListView组件和RecyclerView组件。目前一般推荐使用RecyclerView,因为RecyclerView本身的缓存和效率比ListView高,且支持灵活的布局方式,所以会被大家采用。相信大家在使用ListView时,如果要显示的数据多,肯定多会想到优化Adaper的getView()方法,下面给出一个例子:
public class UsersAdapter extends ArrayAdapter {
private static class ViewHolder {
TextView name;
TextView home;
}
public UsersAdapter(Context context, ArrayList users) {
super(context, R.layout.item_user, users);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
User user = getItem(position);
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.item_user, parent, false);
viewHolder.name = (TextView) convertView.findViewById(R.id.tvName);
viewHolder.home = (TextView)convertView.findViewById(R.id.tvHome);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.name.setText(user.name);
viewHolder.home.setText(user.hometown);
return convertView;
}
}
在这边,我们在ListView需要用到的Adapter中定义了一个内部类ViewHolder,它存储了我们要加载的view的所有子view结构,如果这个view已经被加载过只是暂时被回收, 当需要再次展示的话我们就不需要重新加载整个view,也不需要通过findViewById()来寻找要加载的view的子view,可以直接找到这个view,将要展示的数据设置即可返回显示。
但是在RecyclerView中,我们并不需要做这么多,我们先看一个RecyclerView的简单使用步骤:
定义一个RecyclerView的布局文件以及要展示的item的布局文件
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/t_classList"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp">
android:id="@+id/t_class_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="19sp" />
android:layout_width="match_parent"
android:layout_height="0.5px"
android:background="@color/whiteGray"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:typeface="serif"/>
定义一个adapter
public class ClassAdapter extends RecyclerView.Adapter {
private List classVOs;
static class ClassViewHolder extends RecyclerView.ViewHolder {
View classView;
TextView className;
public ClassViewHolder(View itemView) {
super(itemView);
classView = itemView;
className = (TextView) itemView.findViewById(R.id.t_class_name);
}
}
public ClassAdapter(List classVOs){
this.classVOs = classVOs;
}
@Override
public ClassViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragement_class_item, null, false);
final ClassViewHolder holder = new ClassViewHolder(view);
holder.classView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = holder.getAdapterPosition();
ClassVO classVO = classVOs.get(position);
Toast.makeText(view.getContext(), "you click class "+classVO.getId(), Toast.LENGTH_SHORT).show();
}
});
return holder;
}
@Override
public void onBindViewHolder(ClassViewHolder holder, int position) {
ClassVO classVO = classVOs.get(position);
holder.className.setText(classVO.getName());
}
@Override
public int getItemCount() {
return classVOs.size();
}
}
设置RecyclerView的布局和adapter
recyclerView = (RecyclerView) classListView.findViewById(R.id.t_classList);
layoutManager = new LinearLayoutManager(this.getContext());
recyclerView.setLayoutManager(layoutManager);
if (classVOs!=null){
adapter = new ClassAdapter(classVOs);
}
recyclerView.setAdapter(adapter);
既然我们要说的是RecyclerView中的ViewHolder,但是我们的使用步骤中并没有单独提出ViewHolder,因为在我们上面说的使用步骤的第二步———“定义一个adapter”,就涉及到ViewHolder。
当我们自定义一个adapter时,继承了RecyclerView的一个内部类:
/**
* Base class for an Adapter
*
*
Adapters provide a binding from an app-specific data set to views that are displayed
* within a {@link RecyclerView}.
*/
public static abstract class Adapter {
private final AdapterDataObservable mObservable = new AdapterDataObservable();
private boolean mHasStableIds = false;
/**
* Called when RecyclerView needs a new {@link ViewHolder} of the given type to represent
* an item.
*
* This new ViewHolder should be constructed with a new View that can represent the items
* of the given type. You can either create a new View manually or inflate it from an XML
* layout file.
*
* The new ViewHolder will be used to display items of the adapter using
* {@link #onBindViewHolder(ViewHolder, int, List)}. Since it will be re-used to display
* different items in the data set, it is a good idea to cache references to sub views of
* the View to avoid unnecessary {@link View#findViewById(int)} calls.
*
* @param parent The ViewGroup into which the new View will be added after it is bound to
* an adapter position.
* @param viewType The view type of the new View.
*
* @return A new ViewHolder that holds a View of the given view type.
* @see #getItemViewType(int)
* @see #onBindViewHolder(ViewHolder, int)
*/
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
/**
* Called by RecyclerView to display the data at the specified position. This method should
* update the contents of the {@link ViewHolder#itemView} to reflect the item at the given
* position.
*
* Note that unlike {@link android.widget.ListView}, RecyclerView will not call this method
* again if the position of the item changes in the data set unless the item itself is
* invalidated or the new position cannot be determined. For this reason, you should only
* use the position
parameter while acquiring the related data item inside
* this method and should not keep a copy of it. If you need the position of an item later
* on (e.g. in a click listener), use {@link ViewHolder#getAdapterPosition()} which will
* have the updated adapter position.
*
* Override {@link #onBindViewHolder(ViewHolder, int, List)} instead if Adapter can
* handle efficient partial bind.
*
* @param holder The ViewHolder which should be updated to represent the contents of the
* item at the given position in the data set.
* @param position The position of the item within the adapter's data set.
*/
public abstract void onBindViewHolder(VH holder, int position);
/**
* Called by RecyclerView to display the data at the specified position. This method
* should update the contents of the {@link ViewHolder#itemView} to reflect the item at
* the given position.
*
* Note that unlike {@link android.widget.ListView}, RecyclerView will not call this method
* again if the position of the item changes in the data set unless the item itself is
* invalidated or the new position cannot be determined. For this reason, you should only
* use the position
parameter while acquiring the related data item inside
* this method and should not keep a copy of it. If you need the position of an item later
* on (e.g. in a click listener), use {@link ViewHolder#getAdapterPosition()} which will
* have the updated adapter position.
*
* Partial bind vs full bind:
*
* The payloads parameter is a merge list from {@link #notifyItemChanged(int, Object)} or
* {@link #notifyItemRangeChanged(int, int, Object)}. If the payloads list is not empty,
* the ViewHolder is currently bound to old data and Adapter may run an efficient partial
* update using the payload info. If the payload is empty, Adapter must run a full bind.
* Adapter should not assume that the payload passed in notify methods will be received by
* onBindViewHolder(). For example when the view is not attached to the screen, the
* payload in notifyItemChange() will be simply dropped.
*
* @param holder The ViewHolder which should be updated to represent the contents of the
* item at the given position in the data set.
* @param position The position of the item within the adapter's data set.
* @param payloads A non-null list of merged payloads. Can be empty list if requires full
* update.
*/
可以看到,RecyclerView内部已经帮我们定义好了ViewHolder抽象类,当我们自定义Adapter时,需要定义好要继承ViewHolder的类(Adapter)。
ViewHolder的作用我们在上文介绍使使用ListView时已经说到,简而言之就是提高消息,下面我们看一看源码中对ViewHolder的介绍:
/**
* A ViewHolder describes an item view and metadata about its place within the RecyclerView.
*
*
{@link Adapter} implementations should subclass ViewHolder and add fields for caching
* potentially expensive {@link View#findViewById(int)} results.
*
*
While {@link LayoutParams} belong to the {@link LayoutManager},
* {@link ViewHolder ViewHolders} belong to the adapter. Adapters should feel free to use
* their own custom ViewHolder implementations to store data that makes binding view contents
* easier. Implementations should assume that individual item views will hold strong references
* to ViewHolder
objects and that RecyclerView
instances may hold
* strong references to extra off-screen item views for caching purposes
*/
public static abstract class ViewHolder {
......
}
可以看出两点重要的地方:
Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive {@link View#findViewById(int)} results(adapter应当拥有ViewHolder的子类,并且ViewHolder内部应当存储一些子view,避免时间代价很大的findViewById操作)
Adapters should feel free to use their own custom ViewHolder implementations to store data that makes binding view content easier
其RecyclerView内部定义的ViewHolder类包含很多复杂的属性,内部使用场景也有很多,而我们经常使用的也就是onCreateViewHolder()方法和onBindViewHolder()方法,onCreateViewHolder()方法在RecyclerView需要一个新类型。item的ViewHolder时调用来创建一个ViewHolder,而onBindViewHolder()方法则当RecyclerView需要在特定位置的item展示数据时调用。
参考文章:
android viewholder继承,Android RecyclerView中的ViewHolder相关推荐
- android holder 内部类,Android RecyclerView中的ViewHolder
在使用android提供的组件以列表的格式显示数据时,使用过ListView组件和RecyclerView组件.目前一般推荐使用RecyclerView,因为RecyclerView本身的缓存和效率比 ...
- android onkeydown继承,onKeyDown方法中的返回值
今天调了一个非常蛋疼的bug,花了差不多一个小时的时间,在应用内的某个activity中不能使用设备的音量调节按钮调节音量,开始以为是因为window的某些flag导致的,试了试,貌似没有影响,后来又 ...
- Android踩坑日记:RecyclerView中EditText和ImageView的ViewHolder复用坑
RecyclerView中EditText和ImageView的ViewHolder复用坑 RecyclerView作为ListView的升级版,目前来讲讲开发过程遇到的坑. RecyclerView ...
- int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' on a null.....
今天在做一个即时通讯回话列表时,遇到int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' on a null..空指 ...
- [Android] DiffUtil在RecyclerView中的使用详解
概述 DiffUtil是recyclerview support library v7 24.2.0版本中新增的类,根据Google官方文档的介绍,DiffUtil的作用是比较两个数据列表并能计算出一 ...
- Android Material Design之在RecyclerView中嵌套CardView实现
前言: 第一眼就爱上了Android的Material Design风格.以前倒对Android的界面风格不那么喜欢,扁平化的界面设计真是好看. 其实,这个嵌套操作在实现上并没有什么难点.可是,我还在 ...
- android 日程安排view,RecyclerView 列表控件中简单实现时间线
时间 时间,时间,时间啊:走慢一点吧- 看见很多软件中都有时间线的东西,貌似天气啊,旅游啊什么的最多了:具体实现方式很多,在本篇文章中讲解一种自定义View封装的方式. 效果 先来看看效果. 分析 软 ...
- Android进阶:RecyclerView中DiffUtil的使用
本文转载自:https://blog.csdn.net/zxt0601/article/details/52562770 一.概述 DiffUtil是support-v7:24.2.0中的新工具类,它 ...
- Android 曝光采集,商品view曝光量的统计,判断RecyclerView中某子view是否可见 view是否显示在屏幕中 view展示次数统计...
近期pm提出需要统计首页商品的曝光亮,由于我们的首页是用的recylerview实现的,这里就来讲下如何使用监听recylerview的滚动事件来实现子view的曝光量统计,我们这里说的view都是列 ...
- android适配器封装,Android万能适配器(一)封装ViewHolder
封装 ViewHolder 简单分析ViewHolder封装.ViewHolder内部正常是保存每个页面控件的索引,那么封装时候我们可以使用容器把每个Item布局中的所有控件存储到这个容器里面,每次使 ...
最新文章
- vue-cli-plugin-element的使用
- sshd_config 中文手册
- 【数据结构】集合及运算
- mysql那本书适合初学者_3本书适合初学者
- 搜索日志文件的linux,linux日志查找
- 4月第三周国内域名解析商Top10:万网升至20.32%
- 各种乐器与人声的频率特性说明
- 别天天看看直播了,你知道如何用jmeter对直播间做压测吗
- git revert 之后怎么撤销_git撤销操作
- 简单神经网络结构一键可视化
- 使用a标签下载文件时成了预览,并非是下载
- 三阶魔方还原 - 只需7步6个公式
- 巨潮网怎么下载年报_如何下载A股上市公司EXCEL财务报表
- 个人NAS家庭服务器解决方案概况
- XMLHttpRequest 的 responseType 属性
- PyTorch搭建CNN实现时间序列预测(风速预测)
- 神经网络量化--per-channel量化
- ZYNQ之路--程序固化教程
- 国内首个一体化出行MaaS平台上线
- MATLAB安装文件的目录
热门文章
- Avalondock 第三步 创建停靠面板组
- 交互式反汇编器 linux,Carbon:交互式反汇编工具
- 游戏资源提取工具RPGViewer图像一致转换工具
- 《通信软件开发与应用》课程结业报告
- 采集摄像头RGB565数据并转为bmp图像
- 原创力文档怎么免费下载_简历模板免费资源 word文档模板下载
- Ghostscript沙箱绕过(CVE-2021-3781)分析
- Ghostscript的介绍
- 安装配置管理 之 LumaQQ 的安装和使用
- Win 10 蓝屏,出现DRIVER_POWER_STATE_FAILURE的解决方法