ListView / GirdView Adpater的getView方法,首项多次调用
通过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代替。
釜底抽薪,让列表项不要求重绘。
ListView / GirdView Adpater的getView方法,首项多次调用的更多相关文章
- ListView的adapter中getView方法一直调用
当ListView的高度不定(比如重写ListView搞成可自己主动的扩展的ListView)或 ListView嵌套在SrollView(高度不定)中,listView中的一个item元素改变会使得 ...
- [Android]ListView的Adapter.getView()方法中延迟加载图片的优化
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4139998.html 举个例子吧,以好友列表为例 ListVi ...
- Android LIstView初次创建getview方法执行多次问题
写listview优化的时候,发现Listview初次创建的时候会多次执行getView方法. <?xml version="1.0" encoding="utf- ...
- android ListView 多次调用 getView方法
<ListView android:layout_width="match_parent" android:layout_heig ...
- Android ListView getView()方法重复调用导致position错位
问题现状:Android ListView getView()方法重复调用导致position错位 解决办法:把ListView布局文件的layout_height属性改为fill_parent或者m ...
- [Android]在Adapter的getView方法中绑定OnClickListener比较好的方法
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4146512.html 给ListView中每个item绑定点 ...
- 自定义adapter 的getView方法被重复执行了n次的解决方法
1. getView执行的次数和你的getCount没有直接的关系 ,getCount和你listView里面的条目数量(行数量)有关系 ,getView方法执行次数取决于你屏幕上显示几个条目,比 ...
- [转]Android Adapter以及getView()方法的理解
Android Adapter基本理解: 我的理解是: 1.一个有许多getter的类(就是getView(),getCount()....这些方法) 2.有多少个get方法?都是什么? 这些gett ...
- BaseAdapter的getView()方法
getView()是BaseAdapter的一个重要方法.为了研究getView()方法,使用了以下的类. // apk列表 class list_apk extends BaseAdapter{ p ...
随机推荐
- C/C++读写文件的几种方法fstream fopen、fwrite()、fread()操作
C中采用的主要是文件指针的办法,C++中对文件的操作主要运用了"文件流"(即非标准的输入输出)的思想 c读写文件fopen C 库函数 FILE *fopen(const char ...
- spring cloud工具的概念
spring cloud是一个基于spring boot实现的微服务架构开发工具.它为微服务架构中涉及的配置管理.服务治理.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布式会话和集群状态管 ...
- 对于Element-ui分页进行再次的封装使用
这是我项目的分页的目录结构,话不多说,直接上代码. <template> <div class="pagination-container"> <el ...
- iOS UIView视图的图层控制
1.添加视图 insertSubview:atIndex: //放在子视图数组的具体索引位置 insertSubview:aboveSubview: //某个子视图前面 insertSubvi ...
- iOS copy和mutableCopy 整理
copy 和 mutableCopy 你真的理解吗?最近发现很多面试者基本都不能很好地回答这个问题.所以整理一下. copy和mutableCopy的概念: copy 浅拷贝,不拷贝对象本身,仅仅是拷 ...
- kvm虚拟机控制台登录配置
vm虚拟机能否像xen虚拟机一样通过virsh console 一样采用字符界面进行linux虚拟机控制台呢,答案是肯定的,默认情况下该命令是不起作用的,需要修改相关文件才能实现. 本文出自:http ...
- SATB深入详解与问题剖析【纯理论】
延着上一次[https://www.cnblogs.com/webor2006/p/11147893.html]的理论继续. SATB: 在G1中,使用的是SATB(Snapshot-At-The-B ...
- linux网络编程之posix条件变量
今天来学习posix的最后一个相关知识----条件变量,言归正传. 下面用一个图来进一步描述条件变量的作用: 为什么呢? 这实际上可以解决生产者与消费者问题,而且对于缓冲区是无界的是一种比较理解的解决 ...
- 双端循环列表实现栈(python)
# -*- coding: utf-8 -*- from collections import deque class Node(object): def __init__(self, value=N ...
- python装饰器,迭代器,生成器,协程
python装饰器[1] 首先先明白以下两点 #嵌套函数 def out1(): def inner1(): print(1234) inner1()#当没有加入inner时out()不会打印输出12 ...