1.BaseAdapter.getView缓存问题
为了提高效率,在BaseAdapter.getView中我使用数组缓存了已经创建的view:
        public View getView(int position, View convertView, ViewGroup parent) {
                if (Constant.DEBUG)
                        Log.d(Constant.TAG, "KeyItemAdapter.getview(positon=" + position + ")");
                if (viewArray[position] == null) {
                        viewArray[position] = mInflater.inflate(layoutID, null);
                        // 添加按钮响应函数
                        ImageButton btnSetting = (ImageButton) viewArray[position].findViewById(R.id.ibtn_setting);
                        btnSetting.setOnClickListener(new KeyItemButtonListener(position));                
                }
                //后面代码就是对view的一些设置                
                convertView = viewArray[position];
                return convertView;
现在问题出来了,当listview的数据发生改变时,我调用
adapter.notifyDataSetChanged();
刷新列表,这时候BaseAdapter.getView将会重新执行,重刷新后的列表点击btnSetting就没有反应了,或者第一次点击有反应,后面就没有反应
导致ui出现了一些混乱我进行如下修改就ok:
                if (Constant.DEBUG)
                        Log.d(Constant.TAG, "KeyItemAdapter.getview(positon=" + position + ")");
//                if (viewArray[position] == null) {
//                        viewArray[position] = mInflater.inflate(layoutID, null);
//                        // 添加按钮响应函数
//                        ImageButton btnSetting = (ImageButton) viewArray[position].findViewById(R.id.ibtn_setting);
//                        btnSetting.setOnClickListener(new KeyItemButtonListener(position));
//                }
                viewArray[position] = mInflater.inflate(layoutID, null);
                // 添加按钮响应函数
                ImageButton btnSetting = (ImageButton) viewArray[position].findViewById(R.id.ibtn_setting);
                btnSetting.setOnClickListener(new KeyItemButtonListener(position));
可是不明白为什么会这样,希望高手能够详细解答一下。

解决方案 »

  1.   

    这样肯定效率会很低的,每次都inflate
      

  2.   

     viewArray[position] = mInflater.inflate(layoutID, null);
    这样获取,那是说layoutID还会动态变化么?应该是一个布局文件里有N个控件,但是这个inflate应该只有一次才对,以后用记录的layout来findViewById
      

  3.   

    试试这样:
     
    private View mTmpView = null;
     
     if (mTmpView == null) {
      mTmpView = mInflater.inflate(layoutID, null); 
      }
     // 添加按钮响应函数
      ImageButton btnSetting = (ImageButton) mTmpView.findViewById(R.id.ibtn_setting);
      btnSetting.setOnClickListener(new KeyItemButtonListener(position)); 
     
      

  4.   


       viewArray[position] == null;
     if (viewArray[position] == null) {
      viewArray[position] = mInflater.inflate(layoutID, null);
      // 添加按钮响应函数
      ImageButton btnSetting = (ImageButton) viewArray[position].findViewById(R.id.ibtn_setting);
      btnSetting.setOnClickListener(new KeyItemButtonListener(position));   
      }这样试下
      

  5.   

    为什么要这么写呢,这样每次都会重新加载。
    可以在Oncreate时候初始化XML里的按钮,然后设置按钮响应函数。
    如果你需要对没个view中的button做事件,可以判断点击的position,然后再做处理。
      

  6.   

    晕,楼上看清楚我说的问题再作回答把,你们可以自己做一个简单例子写一个listview,每一项Adapter中包含一个按钮,然后通过一个按键事件改变listview的数据,改变后看看listview界面是否失去了响应,当然
    BaseAdapter.getView要按我上面写的使用缓存实现
      

  7.   

    #6楼你的写我没有看明白???????
      viewArray[position] == null;
     if (viewArray[position] == null) {
      

  8.   

    我不知道lz具体代码怎么写的,我认为要是第一次进入该页面,button肯定有响应,因为第一次viewArray[position] == null,
    要是当listview的数据发生改变时,调用adapter.notifyDataSetChanged();
    这时viewArray[position] != null;
    if里面的不执行了
    不知道分析的对不对,呵呵
      

  9.   

    是的啊,你说的没有错,我原来就是想这样做,目的是不让view重新构造,提高效率,发现adapter.notifyDataSetChanged();后界面无响应才不这样缓存,而是重新赋值
    viewArray[position] = mInflater.inflate(layoutID, null);
    我发帖目的就是想让大家一起看看什么原因造成的
      

  10.   

    我发全一下这个函数吧 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    if (Constant.DEBUG)
    Log.d(Constant.TAG, "KeyItemAdapter.getview(positon=" + position + ")");
    // delete by slcao for reason:使用缓存view notify后会有问题
    // if (viewArray[position] == null) {
    // viewArray[position] = mInflater.inflate(layoutID, null);
    // // 添加按钮响应函数
    // ImageButton btnSetting = (ImageButton) viewArray[position].findViewById(R.id.ibtn_setting);
    // btnSetting.setOnClickListener(new KeyItemButtonListener(position));
    // }
    viewArray[position] = mInflater.inflate(layoutID, null);
    // 添加按钮响应函数
    ImageButton btnSetting = (ImageButton) viewArray[position].findViewById(R.id.ibtn_setting);
    btnSetting.setOnClickListener(new KeyItemButtonListener(position));
    // 根据数据设置显示信息
    Map keyItem = mkeyItemList.get(position + getStartIndex());
    // 标题显示
    int name = ((Integer) keyItem.get(Constant.KEY_ITME_NAME)).intValue();
    TextView lblName = (TextView) viewArray[position].findViewById(R.id.lbl_key);
    lblName.setText(name);
    // value显示
    int value = ((Integer) keyItem.get(Constant.KEY_ITME_VALUE)).intValue();
    TextView lblValSetting = (TextView) viewArray[position].findViewById(R.id.lbl_set_text);
    lblValSetting.setText(value);
    // 是否显示path
    ImageView imgvPath = (ImageView) viewArray[position].findViewById(R.id.imgv_path);
    imgvPath.setVisibility(isSetted ? View.VISIBLE : View.INVISIBLE); convertView = viewArray[position];
    return convertView;
    }
      

  11.   

    这句话就是去掉了这个if判断,和lz后来的做法差不多,要提高效率我建议lz还是加判断,只重构数据发生改变的convertView
      

  12.   

    不用这么麻烦的,原因是android系统会给本身的view添加一个缓存,这个缓存在你notifyDataSetChange后一定要记得刷新。通过调用listView的requestFocusFromTouch()函数来重置你的OnItemClickListener()监听,这样就没有问题了。