ListView優化問題網上已經有很多資料了,下面只是簡單貼一個demo。這里要說一下listview里面checkbox的狀態問題。
~~~
holder.cb_vd.setChecked(state.get(position));
??? ??? ?holder.tv_vd.setText(processList.get(position).processName);
??? ??? ?
??? ??? ?holder.cb_vd
??? ??? ??? ??? ?.setOnCheckedChangeListener(new OnCheckedChangeListener() {
??? ??? ??? ??? ??? ?@Override
??? ??? ??? ??? ??? ?public void onCheckedChanged(CompoundButton buttonView,
??? ??? ??? ??? ??? ??? ??? ?boolean isChecked) {
??? ??? ??? ??? ??? ??? ?// TODO Auto-generated method stub
??? ??? ??? ??? ??? ??? ?if (isChecked) {
??? ??? ??? ??? ??? ??? ??? ?state.put(position, true);
??? ??? ??? ??? ??? ??? ?} else {
??? ??? ??? ??? ??? ??? ??? ?state.put(position, false);
??? ??? ??? ??? ??? ??? ??? ?System.out.println(position+" :"+state.get(position));
??? ??? ??? ??? ??? ??? ?}
??? ??? ??? ??? ??? ??? ?
??? ??? ??? ??? ??? ?}
??? ??? ??? ??? ?});
~~~
通過這段代碼進行注冊checkbox的監聽器,并且進行狀態監聽發現:當listview每一個item滑出屏幕的時候,上面這個函數都會被調用,并且isCheckde都會設為false!覺得非常的不可思議。然后自己查找了很久資料,發現是上面的話調錯位置了。應該是這樣寫的:
~~~
holder.cb_vd
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
state.put(position, true);
} else {
state.put(position, false);
System.out.println(position);
}
}
});
holder.cb_vd.setChecked(state.get(position));
holder.tv_vd.setText(processList.get(position).processName);
~~~
至于原因的話,下面這段話表達的非常的好!
起因還是得講到ListView的回收機制。假如我的ListView最多只能顯示10個View,那么起初就會調用十次getView構造十個全新的View(包括對其中的checkbox設置監聽器)。當我將列表往下拉出現第11個列表項的時候,頂部第一個列表項被隱藏,同樣會再調用一次getView,不過此時getView的參數將返回剛剛被隱藏的第一個列表項的View,并對這個View更改數據作為即將出現的第11個View。問題就出在這里,我把checkbox.setChecked()方法調用放在了設置監聽器前面,此時因為更改了checkbox的狀態,勢必引起觸發狀態更改的監聽器。注意!由于第11個View是用被隱藏的第1個View回收來的,雖然還沒有執行下一行設置監聽器的代碼,但實際上它已經擁有了一個狀態監聽器,這個監聽器是這個View還是作為第一個View時設置。那個時候的監聽器設置更改的第一項的數據,而不是第11項數據。因此,理所當然不能正確更改第11項數據,反而更改了無辜的第1項數據。如果我把兩行代碼順序反過來,先更改監聽器,再設置狀態,引發的監聽器自然也就是新的監聽器,邏輯也就對了。
(轉自 http://www.jb51.net/article/33424.htm)
下面貼上全部代碼:
~~~
package com.example.mytesttwo;
import java.util.Hashtable;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
private ListView lv;
private List<RunningAppProcessInfo> processList;
private Hashtable<Integer, Boolean> state;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
state = new Hashtable<Integer, Boolean>();
lv = (ListView) findViewById(R.id.lv);
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
processList = am.getRunningAppProcesses();
lv.setAdapter(new MyAdapter());
}
private class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
// TODO Auto-generated method stub
return processList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder = null;
if (convertView == null) {
convertView = View.inflate(MainActivity.this, R.layout.iv_item,
null);
holder = new ViewHolder();
holder.tv_vd = (TextView) convertView
.findViewById(R.id.process_name);
holder.cb_vd = (CheckBox) convertView.findViewById(R.id.chose);
convertView.setTag(holder);
state.put(position, false);
} else {
holder = (ViewHolder) convertView.getTag();
if (state.get(position) == null) {
state.put(position, false);
}
}
holder.cb_vd
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked) {
state.put(position, true);
} else {
state.put(position, false);
System.out.println(position);
}
}
});
holder.cb_vd.setChecked(state.get(position));
holder.tv_vd.setText(processList.get(position).processName);
return convertView;
}
}
private class ViewHolder {
public TextView tv_vd;
public CheckBox cb_vd;
}
}
~~~
- 前言
- 安卓ListView一個簡單代碼的注釋和探討
- 安卓wifi熱點編程代碼的若干注釋
- 安卓距離傳感器編程
- 簡單的ScrollView
- 簡單的ListView
- 簡單的ArrayAdapter
- AsyncTask的初步學習
- AsyncTask再度學習
- Handler初步學習
- 開啟系統Activity
- 隱式調用Activity
- Activity的生命周期
- startActivityForResult的初步學習
- 多點觸控拉伸圖片
- LruCache圖片緩存技術
- SQLiteOpenHelper數據庫操作
- 短信攔截器
- 簡單的Notification
- ListView優化以及checkbox狀態問題
- 安卓多線程下載
- 安卓JSON解析初步探討
- 選項卡樣式的fragment
- DrawerLayout實現簡單的側滑功能
- 安卓軟引用解決圖片OOM問題
- 安卓隱式Intent啟動Activity和BroadcastReceiver若干注意點
- Dialog學習筆記
- ActionBar使用