2

我有一个 ListFragment(ListView 的行为应该相同)。列表项中有一些视图,包括微调器。

我想做的是在 Spinner 值发生变化时更新一些支持 ListFragment 适配器的数据。例如,如果 Spinner 在列表项 L[5] 中,并且在位置 1 处选择了 Spinner,我想更新支持数据 L[5].myVal = 1。然后我将调用 notifyDataSetChanged()适配器,以便它可以处理使用新 mVal 值的操作。

我已将 Spinner 包装在 SpinnerWithID 类中,该类将索引保存到与微调器关联的 L 数组中。我使用传入 getView() 的位置更新适配器 getView() 中的 ID。

我看到的问题是,当我的 SpinnerWithID onItemSelectedListener 被执行时,被选择的 SpinnerWithID 可能已被 ListFragment/ListView 回收用于列表中的另一个项目。

我的侦听器函数如下所示:

public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
    SpinnerWithID spinner = (SpinnerWithID)parent;
    if (spinner != null) {          
        BackingData data = DataList.get(spinner.getListIndex());
        // do something with data
    }
}

因此,当它被调用时,微调器的 getListIndex() 返回一个意外的值,因为微调器本身可能已被回收用于列表中的另一个项目。

这是如何处理的?

编辑:我的 getView() 看起来像这样:

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;

    ViewHolder holder = new ViewHolder();

    // First let's verify the convertView is not null
    if (convertView == null) {
        Context context = getContext();

        SpinnerWithID mySpinner = new SpinnerWithID(context);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context,
                R.array.spinner_array, android.R.layout.simple_spinner_item);
        // Specify the layout to use when the list of choices appears
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        // Apply the adapter to the spinner
        mySpinner.setAdapter(adapter);
        mySpinner.setOnItemSelectedListener(myFragment);

        // Add things here to the view
        myLayout.addView(mySpinner);

        v.setTag(holder);
    }
    else {
        holder = (ViewHolder) v.getTag();
    }

    // Update Views based on backing data

    // Keep Spinner synced
    holder.mySpinner.setListIndex(position);

    return v;
}

编辑:按照 buzeeg 发布的链接,我的适配器代码现在如下所示:

public View getView(int position, View convertView, ViewGroup parent) {

    // Build the view or use recycled view

    holder.mySpinner.setTag( Integer.valueOf(position) );
    holder.mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
    {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view,int pos, long id)
        {
            myListFragment.updateBackingData(((Integer)parent.getTag()).intValue(), pos);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            // Another interface callback
        }
    });
}

但是,我仍然有时会更新错误的支持数据项。我的猜测是,在调用 onItemSelected 时,视图已被回收,因此附加到视图的标签已更改为新行。该死。

4

0 回答 0