我用ListView显示数据时,自定义了一个适配器(extends ArrayAdapter),然后重写了getView方法,现在出现一个问题,就是这个getView()方法被重复调用了,比如我的_data中有两条数据,但是log.i("show",house.toString());这句却被执行了4次甚至更多,请问各位这是神马情况?
方法代码如下:
这是自定义的适配器:

package com.hb.puppet.utils;
import java.util.List; import com.hb.puppet.activity.MetaData;
import com.hb.puppet.activity.R;
import com.hb.puppet.entity.House; import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView; public class CustomCollectAdapter extends ArrayAdapter<House> {
private static final String CLASSTAG = CustomCollectAdapter.class
.getSimpleName();
private ListView _listView;
private int _resource;
private List<House> _data;
private LayoutInflater _inflater;
private AsyncLoadImageTask _asyncloader; public CustomCollectAdapter(Context context, ListView listView,
List<House> data) { super(context, 0, data); _resource = R.layout.list_item_collect;
_data = data;
_inflater = (LayoutInflater) context
.getSystemService(context.LAYOUT_INFLATER_SERVICE);
_asyncloader = new AsyncLoadImageTask();
_listView = listView;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
CollectListItemViewCache viewCache = null;
//
final int index = position;
//
final ViewGroup p = parent; if (view != null) {
viewCache = (CollectListItemViewCache) view.getTag();
} else {
view = _inflater.inflate(_resource,null);
viewCache = new CollectListItemViewCache(view);
view.setTag(viewCache);
}
// 房源数据
House house = _data.get(position);
System.out.println(house.toString()); if (house != null) {
//http://www.xxx.com/xxx.jpg
String imageUrl = MetaData.HOST + house.getTitlePic();
ImageView imageView = viewCache.getImageView();
imageView.setTag(imageUrl);
//异步加载图片
new AsyncImageLoaderTask().execute(imageUrl,imageView);
// 房源标题
TextView houseTitle = viewCache.getHouseTitle();
houseTitle.setText(house.getTitle());
// 房源单价
TextView housePrice = viewCache.getHousePrice();
housePrice.setText(house.getSinglePrice() + "元/㎡");
// 房源面积
TextView houseArea = viewCache.getHouseArea();
houseArea.setText(house.getArea() + "㎡");
// 房源户型
TextView houseUnit = viewCache.getHouseUnit();
houseUnit.setText(house.getUnits());
// 单项删除收藏房源
Button delButton = viewCache.getDelButton();
delButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
System.out.println("clicked");
}
});
}
return view;
}
}

异步加载图片:

package com.hb.puppet.utils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView; public class AsyncImageLoaderTask extends AsyncTask<Object, Object, Bitmap>{
private String classTag = AsyncImageLoaderTask.class.getSimpleName();
private ImageView _view;
private HashMap<String, SoftReference<Bitmap>> imageCache; public AsyncImageLoaderTask() {
imageCache = new HashMap<String, SoftReference<Bitmap>>();
} @Override
protected Bitmap doInBackground(Object... params) {
Bitmap bitmap = null;
String url = (String)params[0];
_view = (ImageView)params[1];
if(_view == null){
Log.e(classTag,classTag + " value of _view is not null");
return null;
} if(url != null){
//if current url is int imageCache,get this drawable by it,then return the drawable
if(imageCache.containsKey(url)){
SoftReference<Bitmap> mapSoft = imageCache.get(url);
bitmap = mapSoft.get();
if(bitmap != null){
return bitmap;
}
}
//
URL fromUrl = null;
try {
fromUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)fromUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream input = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(input);
input.close();
} catch (MalformedURLException e) {
Log.e(classTag, classTag + " Method doInBackground -- " +e.getMessage());
} catch (IOException e) {
Log.e(classTag, classTag + " Method doInBackground -- " +e.getMessage());
} catch(Exception e){
Log.e(classTag, classTag + " Method doInBackground -- " +e.getMessage());
} imageCache.put(url, new SoftReference<Bitmap>(bitmap));
} return bitmap;
} @Override
protected void onPostExecute(Bitmap bitmap) {
if(bitmap != null){
System.out.println("onPostExecute");
this._view.setImageBitmap(bitmap);
this._view = null;
}
}
}

这是什么样的情况了,看了网上的资料以后我知道原来没有设置器listview 的布局方式不是fill-parent,而是wrap-content,会计算父控件的高度所以造成了一种反复调用情况,从而次数不确定。
更深层次的解释为:

View在Draw的时候分成两个阶段:measure和layout,在measure阶段时主要就是为了计算两个参数:height和width。而且要注意的是,这是个递归的过程,从顶向下,DecorView开始依次调用自己子元素的measure。计算完成这两个参数后就开始layout,最后再是draw的调用。

对于ListView,当然每一个Item都会被调用measure方法,而在这个过程中getView和getCount会被调用,而且看用户的需求,可能会有很多次调用。

而为什么会有很多组次调用呢?

问题就在于在layout中的决定ListView或者它的父元素的height和width属性的定义了。fill_parent会好一点,计算方法会比较简单,只要跟父元素的大小相似就行,但是即使是fill_parent,也不能给View当饭吃,还是要计算出来具体的dip,所以measure还是会被调用,只是可能比wrap_content的少一点。至于自适应的它会一直考量它的宽和高,根据内容(也就是它的子Item)计算宽高。可能这个measure过程会反复执行,如果父元素也是wrap_content,这个过程会更加漫长。

所以,解决方法就是尽量避免自适应,除非是万不得已,固定大小或者填充的效果会比较好一些。

关于ListView中getView被重复调用的问题的更多相关文章

  1. Android ListView getView()方法重复调用导致position错位

    问题现状:Android ListView getView()方法重复调用导致position错位 解决办法:把ListView布局文件的layout_height属性改为fill_parent或者m ...

  2. 转:ListView中getView的工作原理

    ListView中getView的工作原理: [1]ListView asks adapter “give me a view” (getView) for each item of the list ...

  3. ListView的adapter中getView方法一直调用

    当ListView的高度不定(比如重写ListView搞成可自己主动的扩展的ListView)或 ListView嵌套在SrollView(高度不定)中,listView中的一个item元素改变会使得 ...

  4. android ListView 中getview学习总结

    最近在做android相关的开发,ListView中有一个图片错位的问题,今天查了很多人写的一些东西,所以记录下来,算是一种加深理解吧. ListView是一个非常常用的控件,功能可以扩展的很丰富,而 ...

  5. listview中getview异步加载网络图片

    前言:本以为异步加载挺简单,因为网上代码多,但真想要做好,还真不那么简单,从看代码到弄懂再到自己写,实在是有太多的东西需要学了,用了两天的时间,终于弄出来了,因为用到回调函数,所以理解起来可能难度有点 ...

  6. [转][Android] ListView中getView的原理+如何在ListView中放置多个item

      ListView 和 Adapter 的基础 工作原理: ListView 针对List中每个item,要求 adapter “给我一个视图” (getView). 一个新的视图被返回并显示 如果 ...

  7. CursorAdapter中getView newView bindView异同

    Adapter的作用是界面与数据之间的桥梁,通过设置适配器至ListView控件后(如调用ListView的 setAdapter(ListAdapter adapter)               ...

  8. Android ListView滑动过程中图片显示重复错乱闪烁问题解决

    最新内容建议直接访问原文:Android ListView滑动过程中图片显示重复错乱闪烁问题解决 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及L ...

  9. ListView 中含有 EditText 导致焦点丢失的问题

    ListView 中的 item 中有 EditText 时. 如果activity的输入法选项设置为 android:windowSoftInputMode="adjustResize&q ...

随机推荐

  1. egrep 第几列开始

    第6位开始 egrep -a '^.{5}(0|5)' ${CACSDATA}/outcds.ur5.ca2.txt | sort > ${CACSDATA}/outcds.a.ur5.txt

  2. properties中的编码如何生成:例如\u7AD9\u70B9这种

    在eclipse中的properties中的一种编码,例如\u7AD9\u70B9,是如何自动生成的. 这种编码方式当你要增加某个字段的时候,也要相应的添加这种编码方式下的格式,具体方法如下:

  3. Keystone几种token生成的方式分析

    从Keystone的配置文件中,我们可见,Token的提供者目前支持四种. Token Provider:UUID, PKI, PKIZ, or Fernet 结合源码及官方文档,我们用一个表格来阐述 ...

  4. NandFlash_control

    驱动:编写任何设备的驱动程序,都需要对该设备的原理有一定了解和认识.对于外部设备的访问总是需要通过一个控制器来间接访问,对于这个控制器的控制程序称为驱动程序 Nandflash 原理: 一:角色分析 ...

  5. 富文本插件KindEditor

    具体用法查看官网http://kindeditor.net/doc.php {% load staticfiles %} <!DOCTYPE html> <html lang=&qu ...

  6. JS AngualrJs 指令

    本文基于 AngularJs 1.x 版本 内置指令 布尔属性 根据HTML标准的定义,布尔属性代表一个 true 或 false 值. 当这个属性出现时,这个属性的值就是 true (无论实际定义的 ...

  7. 大型系统中使用JMS优化技巧–Sun OpenMQ

    我们先来看看在Sun OpenMQ系统中 一个持久.可靠的方式传送消息的步骤是怎么样的,如图所示: 查看大图请点击这里 在传送过程中,系统处理JMS消息分为以下两类:   ■ 有效负荷消息,由生成方发 ...

  8. [BZOJ4571][SCOI2016]美味(贪心+主席树)

    经典问题,按位贪心,每次需要知道的是”在这一位之前的位都以确定的情况下,能否找到这一位是0/1的数”,这就是在询问[L,R]内某个值域区间是否有数,主席树即可. #include<cstdio& ...

  9. 2017-2018-1 JAVA实验站 第六、七周作业

    2017-2018-1 JAVA实验站 第六.七周作业 详情请见团队博客

  10. hdu 4417 区间内比h小的数 线段树

    题意求区间内比h小的数的个数 将所有的询问离线读入之后,按H从小到大排序.然后对于所有的结点也按从小到大排序,然后根据查询的H,将比H小的点加入到线段树,然后就是一个区间和. 2015-07-27:专 ...