我参与了一个开源项目,该项目使用ListView
来显示一些数据,每个项目包含2个TextView
项R.id.card_column1
和R.id.card_column2
,这样我们就可以了查看表示大量抽认卡的一些数据的2列列表。
我们有一个固定的数据结构ArrayList<HashMap<String, String>> mCards
,其中包含可以显示在列中的各种键/值对,并使用SimpleAdapter
在给定键/之间进行映射mCards
元素的HashMap中的值对,以及TextView
项如下:
mCardsAdapter = new SimpleAdapter(
this,
mCards,
R.layout.card_item_browser,
new String[] {col1Key, col2Key},
new int[] {R.id.card_column1, R.id.card_column2});
固定mCards
结构与构成列的2 TextView
个元素之间的数据映射需要调整,即我们需要能够更改col1Key
和{{1 }}。我无法找到更改SimpleAdapter
documentation中col2Key
个密钥的方法,因此我目前只需调用from
的{{1}}方法即可实现此方法。每当用户要求更改列时,包含更新密钥的新setAdapter()
。这种方法的问题是ListView
中的垂直位置被重置。
一种解决方案可能是更改数据结构本身,并调用SimpleAdapter
,但是数组可能非常大,因此这种方法会浪费宝贵的RAM,并且可能需要大量的CPU时间来更新数据结构,所以我想避免这种方法。
所以我的问题是:
1)是否可以动态更改适配器中的映射,即更改构造函数中的ListView
对象,而不创建新的notifyDataSetChanged()
?
2)如果没有,那么在不丢失from
中的垂直滚动位置的情况下,更改映射的最佳方法是什么?最好不要消耗任何额外的RAM,或者需要比创建新适配器更多的CPU。
答案 0 :(得分:-1)
感谢Mocialov Boris的提示,以下是完整的答案供参考:
虽然无法更新SimpleAdapter
的映射,但您可以扩展BaseAdapter
并手动实现映射。我们提供了一个setFromMapping()
方法,用于更新数据结构和列之间的映射,并调用notifyDataSetChanged()
。然后,新类MultiColumnListAdapter
的使用方式与使用SimpleAdapter
的方式相同:
public class MultiColumnListAdapter extends BaseAdapter {
private List<? extends Map<String, ?>> mData;
private int mResource;
private String[] mFrom;
private int[] mTo;
private LayoutInflater mInflater;
public MultiColumnListAdapter(Context context, List<? extends Map<String, ?>> data, int resource,
String[] from, int[] to) {
mData = data;
mResource = resource;
mFrom = from;
mTo = to;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public View getView(int position, View convertView, ViewGroup parent) {
// Get the main container view if it doesn't already exist, and call bindView
View v;
if (convertView == null){
v = mInflater.inflate(mResource, parent, false);
final int count = mTo.length;
final View[] columns = new View[count];
for (int i = 0; i < count; i++) {
columns[i]=v.findViewById(mTo[i]);
}
v.setTag(columns);
} else {
v = convertView;
}
bindView(position, v);
return v;
}
private void bindView(int position, View v) {
// Draw the content in the columns
View[] columns = (View[]) v.getTag();
final Map dataSet = mData.get(position);
for (int i = 0; i < mTo.length; i++) {
TextView col = (TextView) columns[i];
col.setText((String) dataSet.get(mFrom[i]));
}
}
public void setFromMapping(String[] from){
mFrom = from;
notifyDataSetChanged();
}
public String[] getFromMapping(){
return mFrom;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
}