Android Loaders と Fragments を使用して奇妙な状況に気づきました。向きの変更後に LoaderManager.initLoader() を呼び出すと、 onLoadFinished は呼び出されません (ただし、ドキュメントではこれに備えておく必要があることが示唆されています) が、この後 2 回呼び出されます。これは、同じ状況を説明する Google グループに投稿するためのリンクですhttps://groups.google.com/forum/?fromgroups#!topic/android-developers/aA2vHYxSskU。Fragment.onActivityCreated() で単純なローダーを初期化して、これが発生するかどうかを確認するサンプル アプリケーションを作成しました。誰もこれに気づきましたか?
10 に答える
Fragment の onResume() コールバック内に initLoader() メソッドを配置できます。その場合、ローダーの onLoadFinished() はもう 2 回呼び出されません。
@Override
public void onResume()
{
super.onResume();
getLoaderManager().initLoader(0, null, this);
}
initLoaderのドキュメントによると、
呼び出しの時点で呼び出し元が開始状態にあり、要求されたローダーがすでに存在し、そのデータを生成している場合、onLoadFinished(Loader、D)をコールバックします。
このサンプルでonStartLoading関数のようなものを実装することをお勧めします
簡単なテストのためにあなたは試すことができます:
@Override protected void onStartLoading() {
forceLoad();
}
これにより、loadInBackground関数が起動し、次にフラグメントでonLoadFinishedが起動します。
とにかく、あなたがいくつかのコードを添付するならば、私はあなたにもっと助けを与えようとします。
問題は、2 回呼び出されたことです:
1. Fragment.onStart から
2. FragmentActivity.onStart から
唯一の違いは、Fragment.onStart で mLoaderManager != null かどうかをチェックすることです。これが意味することは、onActivityCreated のように、onStart の前に getLoadManager を呼び出すと、ロード マネージャーが取得/作成され、呼び出されるということです。これを避けるには、onResume のように後で呼び出す必要があります。
initLoader
から呼び出すと、onActivityCreated
回転を検出できます:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
// fresh new fragment, not orientation/config change
getLoaderManager().initLoader(YOUR_LOADER_ID, null, mCallbacks);
}
...
}
このようにして、ローダーは期待どおりに動作し、単一のonLoadFinished
呼び出しになります。
ローテーション時に呼び出されなくなったため、ローダーのデータが必要な場合は、たとえば をオーバーライドして、フラグメントに保持できますonSaveInstanceState
。
編集:
ローダーonLoadFinished
のloadInBackground
. これを修正するにはinitLoader
、ローダーからのデータがまだ利用できない場合、ローテーション後に呼び出す必要があります。
それが役立つことを願っています。
このテーマの検索はすべて必然的にここで終了するため、私の経験を追加したかっただけです. @jperera が言ったように、犯人は、ローダーが既に存在する場合、LoaderManager が onLoadFinished() を呼び出すことでした。私の場合、FragmentPager にフラグメントがあり、2 つのタブをスクロールしてから、その横にもう一度スクロールすると、古いフラグメントが作成され始めました。
initLoader() を onCreate() 内に配置するとコールバックが 2 回発生するため、initLoader() を onResume() 内に配置しました。しかし、一連のイベントは onCreate() になり、LoaderManager はローダーが存在するためコールバックを呼び出し、次に onResume() が呼び出され、別の initLoader() および onLoadFinished() シーケンスをトリガーします。IE、別の二重コールバック。
解決
「マット」による簡単な解決策を見つけました。すべてのデータがロードされたら (複数のローダーがある場合)、すべてのローダーを破棄して、それらのコールバックが余分に呼び出されないようにします。
私はこの問題に直面していますが、私はdestroyloader(YOUR_ID)
in loaderfinished メソッドを呼び出すのに慣れていました。その後、ローダーは backgrdound タスクを 2 回呼び出すことはありません。