是否可以更改现有SimpleAdapter的映射?

时间:2014-04-09 07:59:30

标签: android

我参与了一个开源项目,该项目使用ListView来显示一些数据,每个项目包含2个TextViewR.id.card_column1R.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 documentationcol2Key个密钥的方法,因此我目前只需调用from的{​​{1}}方法即可实现此方法。每当用户要求更改列时,包含更新密钥的新setAdapter()。这种方法的问题是ListView中的垂直位置被重置。

一种解决方案可能是更改数据结构本身,并调用SimpleAdapter,但是数组可能非常大,因此这种方法会浪费宝贵的RAM,并且可能需要大量的CPU时间来更新数据结构,所以我想避免这种方法。

所以我的问题是:

1)是否可以动态更改适配器中的映射,即更改构造函数中的ListView对象,而不创建新的notifyDataSetChanged()

2)如果没有,那么在不丢失from中的垂直滚动位置的情况下,更改映射的最佳方法是什么?最好不要消耗任何额外的RAM,或者需要比创建新适配器更多的CPU。

1 个答案:

答案 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;
    }
}