当我在写一个android应用的时候遇到了这样一个需求:
有个ListView,里面的item都有图片和文字,当一个item被点击的时候显示在此item上显示图片和一个进度条,当另一个item被点击的时候隐藏上一次被电击item的图片和进度条,显示当前被点击item的图片和进度条
我的有关代码是这样的,用的是simpleAdapter
我的思路是就这样的,先把ListView的所有item遍历,隐藏我该隐藏的控件,然后显示当前被点击item的要显示的控件(progressbar和playing_effect)
不过问题出现了,点击之后的效果特别卡,不知道怎么回事点击40-50次之后就出现手机内存不足的情况,难道我的思路一开始是错误的吗?还是需要优化?耗内存是怎么回事啊
谢谢
public class MainActivity extends AppCompatActivity {
ArrayList<Boolean> itemState = new ArrayList<>();
int checkedItemIndex = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for (int s=0;s<20;s++){
itemState.add(false);
}
class AudioListAdapter extends SimpleAdapter{
public AudioListAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
//
if (itemState.get(position)){
// 设置点击状态
v.findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
v.findViewById(R.id.playing_effect).setVisibility(View.VISIBLE);
}else {
// 设置未点击状态
v.findViewById(R.id.progressBar).setVisibility(View.GONE);
v.findViewById(R.id.playing_effect).setVisibility(View.GONE);
}
//
return v;
}
}
final ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>>();
for (int i = 0; i < 10; i++){
HashMap<String,Object> map = new HashMap<String, Object>();
map.put("song","song name "+i);
map.put("singer","singer "+i);
map.put("currentTime","01:3"+i);
map.put("allTime","04:5"+i);
listItem.add(map);
}
final ListView listView = (ListView)findViewById(R.id.listView);
final AudioListAdapter audioListAdapter = new AudioListAdapter(
this,
listItem,
R.layout.item,
new String[]{"song","singer","currentTime","allTime"},
new int[]{R.id.song,R.id.singer,R.id.currentTime,R.id.allTime}
);
listView.setAdapter(audioListAdapter);
// onclick
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//
if (checkedItemIndex>=0){
itemState.set(checkedItemIndex,false);
}
checkedItemIndex = position;
itemState.set(position,true);
audioListAdapter.notifyDataSetChanged();
//
}
});
}
@Override
public void onStart(){
super.onStart();
}
}
上面我把所有代码给贴出来的,我按楼下回复里的想法去做的,我发现结果同样很卡,内存耗得更快,大神们看一下吧
谢谢
樓上兩位已經說的比較清楚了,自己維護一個列表,然後在getView中根據列表的狀態繪製不同的View。
之前你的方法需要遍歷並創建所有itemView的實例,無論是對cpu還是內存都有很大的壓力,所以會卡,在item數量未知的前提下最好不要遍歷,保存一個上次點擊的index就行了。
隨便寫了些偽代碼,大概是這樣的
----------------------------分割線------------------- --
你getView部分的程式碼有問題,在這裡你應該建立/重複使用convertView
我說下我的思路吧:
把item的點擊狀態都存在adapter中,每次點擊只要去更新adapter中具體item的某個屬性就行了。接著在getView裡根據這個屬性的不同做不同的處理。
把顯示/隱藏的邏輯寫在listView的adapter的getView方法,點擊的時候呼叫notifyDataSetChanged就可以了
3樓正解,自己新建一個boolean類型的list用以保存每個item的狀態,每次點擊先將下標currentitemindex的item屬性改為false,將下標position的item屬性設為true。然後更新curreentitemindex.最後刷新adapter