私は ListFragment を持っています (ListView は同じように動作するはずです)。リスト項目には、スピナーを含むいくつかのビューがあります。
私がやりたいことは、Spinner 値が変更されたときに ListFragment アダプターをサポートするデータの一部を更新することです。たとえば、スピナーがリスト アイテム L[5] にあり、スピナーが位置 1 で選択されている場合、バッキング データ L[5].myVal = 1 を更新します。新しい 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 が呼び出されるまでにビューがリサイクルされたため、ビューに付けられたタグが新しい行に変更されています。ダーン。