ListView / GirdView Adpater的getView方法,首项多次调用
2024-08-27 05:59:51
通过Adapter为AbslistView
提供内容是一个常见的做法:在ListView或者GridView的Adapter中的getView()
方法中,加入一行日志,看getView()
被调用的情况
public View getView(int position, View convertView, ViewGroup parent) {
Log.d('cube_list',
String.format("getView %s, %s", position, convertView == null));
// 创建
if (convertView == null) {
}
// 复用
else {
}
}
问题表现
对于ListView,我们使用如下的一个xml文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@+id/ly_image_list_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="@null"
android:fadingEdge="none"
android:listSelector="@android:color/transparent"
android:padding="10dp"
android:scrollbarStyle="outsideOverlay" />
</RelativeLayout>
getView 方法返回的view含有一个网络图片,下载完成后,会导致重新绘制。
运行程序,在Logcat中 有可能 会看到getView
会被打印出很多条。
0
03-15 14:32:41.980 cube_list﹕ getView 0, true
03-15 14:32:41.980 cube_list﹕ getView 1, false
03-15 14:32:41.980 cube_list﹕ getView 2, false
03-15 14:32:41.990 cube_list﹕ getView 3, false
03-15 14:32:41.990 cube_list﹕ getView 4, false
03-15 14:32:41.990 cube_list﹕ getView 0, false
03-15 14:32:41.990 cube_list﹕ getView 1, false
03-15 14:32:41.990 cube_list﹕ getView 2, false
03-15 14:32:41.990 cube_list﹕ getView 3, false
03-15 14:32:41.990 cube_list﹕ getView 4, false
03-15 14:32:42.000 cube_list﹕ getView 0, false
03-15 14:32:42.010 cube_list﹕ getView 1, true
03-15 14:32:42.010 cube_list﹕ getView 2, true
03-15 14:32:42.010 cube_list﹕ getView 3, true
03-15 14:32:42.020 cube_list﹕ getView 4, true
第一页之后,第0项不再被绘制,但GridView 情况却糟糕多了, 滑动的过程,第0项还在不停被绘制。
原因分析
起因:类似这样的情况,都是加入了列表项之后,列表项自身的一些操作,比如加入图片,导致整个view重新绘制。在重新绘制的过程中,onMeasure方法会创建出列表项来确定大小。
ListView
在onMeasure()
时:
- 如果宽度或者高度的状态为 UNSPECIFIED, 会多次绘制列表首项,直到大小确定为止。
- 如果高度的状态为AT_MOST, 会绘制多个列表项进行确定大小。
主要代码如下:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
// ViewMode 处于UNSPECIFIED 状态,绘制首项来确定大小
mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED
|| heightMode == MeasureSpec.UNSPECIFIED)) {
// getView(0)
final View child = obtainView(0, mIsScrap);
// other code
}
}
// other code
// AT_MOST 状态,绘制多个列表项以确定高度。
if (heightMode == MeasureSpec.AT_MOST) {
// 会调用多个getView,这些view将不会被复用
heightSize = measureHeightOfChildren(widthMeasureSpec, 0,
NO_POSITION, heightSize, -1);
}
// other code
}
解决方案:
如果ListView
大小未决,则会绘制列表项,以确定自身大小。让ListView
大小处于EXACTLY
状态即可。
根据 Android中View大小的确定过程,所描述:
- 如果ListView父容器大小确定,设置尺寸为
match_parent
不会出现此问题。 - 不管父容器什么状态,
ListView
大小为确定数值不会出现此问题。
GirdView
GridView
看起来比较无解,每次onMeasure()
都会导致列表首项被绘制。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// other code
mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
final int count = mItemCount;
if (count > 0) {
final View child = obtainView(0, mIsScrap);
// ...
}
// ...
}
只要重新确定大小,首项就一定会被重绘,这个是非常险恶的。从onMeasure
的实现来看,几乎无法避免,只能从业务方入手。
如果是类似九宫格的应用场景,这里有一个解决方案。Gridview的错误用法及替代方案
一定有翻屏的需求,可用ListView代替。
釜底抽薪,让列表项不要求重绘。
最新文章
- FMDB的使用方法
- JavaScript 作用域知识点梳理
- poj 1328 Radar Installation
- http协议读书笔记2-连接管理
- 20150604_Andriod 窗体PopupWindow
- codeforce 702D Road to Post Office 物理计算路程题
- cocos2d-x 技能冷却特效
- jquery左右自适应伸缩插件
- UVALive - 4621 Cav 贪心 + 分析
- 解决 Visual Studio 点击添加引用无反应的问题
- 异步编程(async&;await)
- Git与GitHub的基本使用
- linux系统切换用户
- USACO Arithmetic Progressions(暴力)
- Fiddler 抓包工具总结-bpafter
- 师傅领进门之6步教你跑通一个AI程序!
- 20145314郑凯杰 《Java程序设计》实验四 实验报告
- SQL Server数据库常用的T-SQL命令
- Spring学习(三)—— 自动装配案例分析
- 禁止网页右键和复制,ctrl+a都不行。取消页面默认事件【全】。
热门文章
- 【转载】Session对象的作用以及常见属性
- https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce/repodata/repomd.xml:HTTPS Error 404 - Not Found
- 清楚html和css标签自带默认样式
- ubuntu18.04 安装idea
- poi 读取word 遍历表格和单元格中的图片
- Linux误删python导致yum不可用,删除重装方法。
- Python面向对象Day2
- C#一些不太熟悉的类——扩展学习
- 运输层5——TCP报文段的首部格式
- 回归分析特征选择(包括Stepwise算法) python 实现