关于ListView中getView被重复调用多次的问题

来源:互联网 发布:网络电话卡营销方案 编辑:程序博客网 时间:2024/04/28 08:15

我用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,这个过程会更加漫长。

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


原文链接:http://www.cnblogs.com/manuosex/p/3426160.html

0 0
原创粉丝点击