zoukankan      html  css  js  c++  java
  • 关于ListView中getView被重复调用的问题

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

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

  • 相关阅读:
    PHP多进程编程
    2013年中国数据库大会PPT
    python学习笔记
    策略分析方法论
    Linux操作系统下定时发送邮件
    PHP初学
    Linux操作下的进程管理利器 Supervise
    Hive中小表与大表关联(join)的性能分析zz
    工作杂记4
    PostgreSQL 13 源码安装【转载】 规格严格
  • 原文地址:https://www.cnblogs.com/manuosex/p/3426160.html
Copyright © 2011-2022 走看看