AndroidのArrayAdapterのカスタム実装に奇妙な問題があります。いくつかの背景を与えるために、現在のスクロール位置を保持しながらListViewの内容を更新しようとしています。Android ArrayAdapterがクリアされませんか?
私は、リストビューに表示されているデータを更新するスレッドを実行するサービスを持っています。そのデータはArrayListに格納され、そのArrayListを使用してListViewのカスタムArrayAdapterを生成します。アダプタは、ListView内の項目が押されたとき(項目の追加または削除)にも更新されます。私は、新しいタイプの変更があるたびに新しいアダプタを作成してから、この新しいアダプタをListViewに設定していました。これはうまくいきましたが、毎回ListViewが上にスクロールしました。私のアプリケーションの性質上、これは望ましくありませんでした。 ListViewの現在のスクロール位置は更新の間に維持されなければなりません。
新しいアダプタを作成する代わりに、アダプタのclear()メソッドを使用して更新する必要があるアダプタをクリアしてから、アダプタのadd()メソッドを使用してアダプタのアイテムを再構築しました。これらのメソッドの両方がアダプタで呼び出されています。アダプターはコンストラクターでnotifyDataOnChangeに設定されているので、毎回notiftyDatasetChanged()を手動で呼び出す必要はありません(私の問題があれば手動で呼び出すようにしましたが)。
public class RealmAdapter extends ArrayAdapter<Realm>
{
Context c;
public RealmAdapter(Context context, int resource, int textViewResourceId)
{
super(context, resource, textViewResourceId);
setNotifyOnChange(true);
c = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
...
}
...
}
かいつまんで、ここに私の問題です:
は、ここに私のカスタム・アダプターは次のようになります。アダプタでclear()を呼び出すと、アダプタはクリアされていません。
ここでは、私のonPostExecuteのスニペットが更新されているスレッドにあります。私はそれをここに置くようにしているので、UIスレッドで更新しています。私はまた、この正確なコードを自分のUIアクティビティのプライベートメソッドにコピーしました。このコードのいずれかの場所では動作しません。例として
appState.favoriteAdapter.clear();
Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount());
for(Realm r : appState.favorites) {
appState.favoriteAdapter.add(r);
}
Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount());
、上記アダプタは同様にgetCountを(呼び出して、その中の3項目を持っていた場合)、右(クリア後)は、同様に3の代わりに0を返しますappState.favorites ArrayListに2つの項目しかない場合、ループの後のgetCount()は2ではなく3を返しています。アダプタはこれらの呼び出しに応答しないため、どのような方法でも更新することはできません。 Logcatを後で投稿すると便利ですが、例外や表示される有用なものはありません。
私の頭が長時間バストした後、私が見ている問題は、アダプタがそれを変更するメソッドへの呼び出しに応答していないということです。私は空のArrayListをアダプタのsuper()呼び出しに渡そうとしましたが、これは役に立ちません。 ArrayAdapterを間違って使用していますか?私は全面的に調査しましたが、基になる配列を変更して更新することを期待したり、アダプタにケーパビリティを設定したりしてnotifyDatasetChanged()を呼び出したり、サポートされていない基になるコレクションの操作
favoriteAdapterの宣言は非常に単純であり、自分のアプリケーションのクラスに含まれる:
if(appState.favoriteAdapter == null) {
appState.favoriteAdapter = new RealmAdapter(c, R.layout.list_item, R.layout.realm_entry, appState.favorites);
}
else {
appState.favoriteAdapter.clear();
Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount());
for(Realm r : appState.favorites) {
appState.favoriteAdapter.add(r);
}
Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount());
}
上記のコードは両方である:ここ
public RealmAdapter favoriteAdapter;
上記からfavoriteAdapterの初期化です私のUIスレッドと、更新されたデータをダウンロードするスレッド。フィルター上のコードの下側に
は場所に置かれている:
if(appState.favoriteAdapter != null && RealmSelector.realmFilter != null) appState.favoriteAdapter.getFilter().filter(RealmSelector.realmFilter.getText().toString());
フィルタリストをクリア影響しますか?ロジックは指示しません。
正しく使用しているようです。私はArrayListのコードを見てきましたが、それはかなり簡単です。 あなたはアダプターで何らかのフィルタリングを使用していますか? (それは物事を少し複雑にすることができます)。 アダプタの初期化とappState.favoriteAdapterの宣言をポストできますか? – balazsbalazs
確かに。宣言は非常に単純で、私のアプリケーションクラスに含まれています: public RealmAdapter favoriteAdapter; 実際の初期化は、どのスレッドがアダプタに最初にアクセスするかによって、UIアクティビティまたはスレッドのいずれかで発生します。実際には、前に投稿したコードの拡張です: if(appState.favoriteAdapter == null){ \t appState.favoriteAdapter = new RealmAdapter(c、R.layout.list_item、R.layout.list_item、R.layout.realm_entry、appState.favorites) ; } 私はフィルタを持っていますが、私もそれを投稿します。コメントの書式設定が奇妙なので、オリジナルの投稿も編集します。 – Eluamous
誰もが考えている?私はまだ失われています... – Eluamous