Android AsyncTaskLoaderが注意しなければならない問題
6995 ワード
AsyncTaskLoaderを使用すると、次の2つの問題が発生します.
1.AsyncTaskLoaderを継承して必要な方法を実現した後、loadInBackground()が実行されていないことを発見する
インターネットで検索すると、次のような解決策が得られます.
AsyncTaskLoaderを継承すると、システム呼び出しのために次の方法を再ロードする必要があります.
2.問題1の解決策を使った後、Loaderは仕事を始めましたが、また新しい問題に遭遇しました.ActivityにListViewを書きました.ListViewのデータはAsyncTaskLoaderを通じて
を入力し、現在のActivityから別のActivityにジャンプしてbackキーを押して戻ると問題ありませんが、ListViewのいずれかをクリックすると、次のエラーが表示されます.
E/AndroidRuntime(1141): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(16908298, class android.widget.ListView) with Adapter(class com.study.ActivityAdapter)]
以下は私がAsyncTaskLoaderをカスタマイズしたコードです.
ListViewデータを更新する操作はUIスレッドで行われるので、システムが知らないところでデータを更新してListViewに通知しないはずです.
Activityを表示JAvaのソースコードは次のように表示されます.
Activityが回復すると、onStart関数が再呼び出され、最終的には私たちのLoaderのonStartLoading関数が呼び出されます.
私たちのonStartLoading関数はこうです.
つまり、いずれにしてもバックグラウンドでデータを再ロードし、システム呼び出しであるため、ListViewに通知することなく、データの不同期を招く.
ここで、ソリューションは次のようになります.
以下のように変更します.
1.AsyncTaskLoaderを継承して必要な方法を実現した後、loadInBackground()が実行されていないことを発見する
インターネットで検索すると、次のような解決策が得られます.
AsyncTaskLoaderを継承すると、システム呼び出しのために次の方法を再ロードする必要があります.
@Override
protected void onStartLoading() {
// TODO Auto-generated method stub
super.onStartLoading();
forceLoad();
}
2.問題1の解決策を使った後、Loaderは仕事を始めましたが、また新しい問題に遭遇しました.ActivityにListViewを書きました.ListViewのデータはAsyncTaskLoaderを通じて
を入力し、現在のActivityから別のActivityにジャンプしてbackキーを押して戻ると問題ありませんが、ListViewのいずれかをクリックすると、次のエラーが表示されます.
E/AndroidRuntime(1141): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(16908298, class android.widget.ListView) with Adapter(class com.study.ActivityAdapter)]
以下は私がAsyncTaskLoaderをカスタマイズしたコードです.
public class ActivityListLoader extends AsyncTaskLoader{
private Context context;
private Bundle args;
private String path;
private List
ListViewデータを更新する操作はUIスレッドで行われるので、システムが知らないところでデータを更新してListViewに通知しないはずです.
Activityを表示JAvaのソースコードは次のように表示されます.
protected void onStart() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
mCalled = true;
if (!mLoadersStarted) {
mLoadersStarted = true;
if (mLoaderManager != null) {
mLoaderManager.doStart(); // Loader onStartLoading
} else if (!mCheckedForLoaderManager) {
mLoaderManager = getLoaderManager(null, mLoadersStarted, false);
}
mCheckedForLoaderManager = true;
}
getApplication().dispatchActivityStarted(this);
}
Activityが回復すると、onStart関数が再呼び出され、最終的には私たちのLoaderのonStartLoading関数が呼び出されます.
私たちのonStartLoading関数はこうです.
@Override
protected void onStartLoading() {
// TODO Auto-generated method stub
super.onStartLoading();
forceLoad();
}
つまり、いずれにしてもバックグラウンドでデータを再ロードし、システム呼び出しであるため、ListViewに通知することなく、データの不同期を招く.
ここで、ソリューションは次のようになります.
以下のように変更します.
@Override
protected void onStartLoading() {
// TODO Auto-generated method stub
super.onStartLoading();
if(data.size() == 0)
forceLoad();
}