Rumah > Soal Jawab > teks badan
当我在写一个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();
}
}
上面我把所有代码给贴出来的,我按楼下回复里的想法去做的,我发现结果同样很卡,内存耗得更快,大神们看一下吧
谢谢
PHP中文网2017-04-17 17:43:00
楼上两位已经说的比较清楚了,自己维护一个列表,然后在getView中根据列表的状态绘制不同的View。
之前你的方法需要遍历并创建所有itemView的实例,无论是对cpu还是内存都有很大的压力,所以会卡,在item数量未知的前提下最好不要遍历,保存一个上次点击的index就行了。
随便写了些伪代码,大概是这样的
ArrayList<Boolean> list = new ArrayList<>();
int listClickedItemIndex = -1;
public View getView(int position, View convertView, ViewGroup parent) {
if(list.get(position)){
//设为点击状态
}else{
//设为未点击状态
}
return convertView;
}
public void onItemClick(int position){
if(listClickedItemIndex >= 0){
list.set(listClickedItemIndex,false);
}
listClickedItemIndex = position;
list.set(position,true);
adapter.notifyDataSetChanged();
}
----------------------------分割线---------------------
你getView部分的代码有问题,在这里你应该创建/复用convertView
怪我咯2017-04-17 17:43:00
我说下我的思路吧:
把item的点击状态都存在adapter中,每次点击只要去更新adapter中具体item的某个属性就行了。接着在getView里根据这个属性的不同做不同的处理。
黄舟2017-04-17 17:43:00
3楼正解,自己新建一个boolean类型的list用以保存每个item的状态,每次点击先将下标currentitemindex的item属性改为false,将下标position的item属性设为true。然后更新curreentitemindex.最后刷新adapter