リスト ビューにカスタム リスト アダプターを使用しています。リスト ビューにボタンを定義し、クリック イベントは機能しますが、問題は、リストがスクロールされると、複数のビューが同じボタンにバインドされることです。ボタンをクリックすると、関連付けられた各ビューに関連付けられたイベントが発生します。
どうすればこれに対処できますか?
リスト ビューにカスタム リスト アダプターを使用しています。リスト ビューにボタンを定義し、クリック イベントは機能しますが、問題は、リストがスクロールされると、複数のビューが同じボタンにバインドされることです。ボタンをクリックすると、関連付けられた各ビューに関連付けられたイベントが発生します。
どうすればこれに対処できますか?
Stuart は完全に正しいです。問題は、ListView のビューが (別のオブジェクトの作成を避けるために) 再利用され、リストの別の部分が表示されるため、新しい位置で使用されなくなったビューを取得できることです。したがって、コードはこれを適切に処理する必要があります。monodroid の Java オブジェクトのガベージ コレクションがうまく機能しないことを追加したいと思います。私の経験では、Java.Lang.Object から派生したオブジェクトを多数作成すると、アプリケーションがクラッシュします。そう:
新しい行ごとに新しいビューを作成すると、すぐにアプリケーションがクラッシュするため、可能な限り convertView を再利用する必要があります。
タグの型は Java.Lang.Object であるため、WrappedPosition は Java オブジェクトから派生する必要があります。これは、毎回新しいインスタンスを作成するのではなく、同じインスタンスを再利用する必要があることを意味します。
クリックハンドラーを別のメソッドに移動すると、サブスクライブする前にサブスクライブを解除するだけで済むため、「ビューが null の場合」というロジックは必要ありません。
役に立つと思われる場合は、その仕組みを説明するコードの例をここに投稿することがあります。かなり大きいので、最初は投稿しないでください:)
リストの仕組み、特に convertView の使用方法を誤解していると思います。
Android の ListViews は UI を仮想化します - ListBoxes が WP で行うように、また UITableViews が iOS で行うように
これが意味することは、基になるリストに 1000 個の項目があり、画面に 10 個の項目しかない場合、リストは 10 個の「コンテナー」を作成してリスト項目を表示し、それらのコンテナーを使用してコンテンツのみを表示するということです。当時視野に入っています。
これを行う方法は、Adapter (特に、convertView をパラメーターの 1 つとして受け取る GetView コールバック) を使用することです。
GetView 実装で新しいビューを作成することを選択した場合は、コールバックで新しいイベントをサブスクライブできます...
代わりに、GetView 実装で convertView を使用することを選択した場合は、最初に古いイベントのサブスクライブを解除することなく、コールバックで新しいイベントをサブスクライブしないでください。
たとえば、あなたのコードは現在、この擬似のようなことをしていると思います:
public View GetView(int pos, View convertView)
{
TextView toShow = convertView as TextView;
if (toShow == null)
{
toShow = new TextView();
}
toShow.Text = "Item at position " + i;
toShow.Click += (s,e) => {
// do something
};
return toShow;
}
コードの問題は、Click を頻繁に購読することです...次のような方法で解決する必要があります。
public View GetView(int pos, View convertView)
{
TextView toShow = convertView as TextView;
if (toShow == null)
{
toShow = new TextView();
toShow.Click += (s,e) => {
// do something with the position embedded in toShow.Tag
};
}
toShow.Text = "Item at position " + i;
toShow.Tag = new WrappedPosition(i);
return toShow;
}
とにかくそれは私の推測です:)