我有一个应用程序,我希望一次一行可以有一定的颜色。这似乎在95%的时间内起作用,但有时不是只有一行具有这种颜色,它将允许多行具有颜色。具体来说,一行被设置为在点击时具有“特殊”颜色。在极少数情况下,尽管调用了setBackgroundColor,但最后一行被点击仍会保留颜色。
private OnItemClickListener mDirectoryListener = new OnItemClickListener(){
public void onItemClick(AdapterView parent, View view, int pos, long id){
if (stdir.getStationCount() == pos) {
stdir.moreStations();
return;
}
if (playingView != null)
playingView.setBackgroundColor(Color.DKGRAY);
view.setBackgroundColor(Color.MAGENTA);
playingView = view;
playStation(pos);
}
};
我已经通过print语句确认始终调用将行设置为灰色的代码。
有人能想象出这段代码可能间歇性失败的原因吗?如果存在导致它的模式或条件,我无法分辨。
我认为它可能与活动生命周期有关,将“playingView”变量设置为null,但我无法通过切换活动或锁定手机来可靠地重现问题。
private class DirectoryAdapter extends ArrayAdapter {
private ArrayList<Station> items;
public DirectoryAdapter(Context c, int resLayoutId, ArrayList<Station> stations){
super(c, resLayoutId, stations);
this.items = stations;
}
public int getCount(){
return items.size() + 1;
}
public View getView(int position, View convertView, ViewGroup parent){
View v = convertView;
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (position == this.items.size()) {
v = vi.inflate(R.layout.morerow, null);
return v;
}
Station station = this.items.get(position);
v = vi.inflate(R.layout.songrow, null);
if (station.playing)
v.setBackgroundColor(Color.MAGENTA);
else if (station.visited)
v.setBackgroundColor(Color.DKGRAY);
else
v.setBackgroundColor(Color.BLACK);
TextView title = (TextView)v.findViewById(R.id.title);
title.setText(station.name);
return v;
}
};
答案 0 :(得分:2)
ListViews不会为列表中的每个项创建包含视图的实例,而只会为屏幕上实际可见的项创建实例。出于性能原因,他们尝试尽可能少地保留视图,并回收它们。这就是convertView参数。
当视图滚动离开屏幕时,它可能会被回收或销毁。您不能保留对旧视图的引用,并假设它将引用您将来期望它的项目。您应该保存所需列表项的ID,而不是查看它。
此外,您的实施还存在其他一些问题(从最佳实践角度来看)。您似乎忽略了convertView参数并且每次都从头开始创建新视图。如果您有一个长列表,这可能会导致您的应用程序在滚动时陷入困境。其次,不要像你那样添加“更多”元素,而是使用setFooterView()设置它。
来自Google I / O 2010的excellent talk on the ListView涵盖了这些问题和其他问题。这是一个小时,但绝对值得一看。