16

LoaderManagerでローダーを識別するときは、一意のIDを使用します。私はそれらのIDがどれくらいユニークでなければならないかについて尋ねています。LoaderManagerの有効範囲は何ですか?

すべてのアクティビティとフラグメントに独自のLoaderManagerがありますか?フラグメントは、それらが接続されているアクティビティのLoaderManagerを使用していますか?アプリケーションが所有するLoaderManagerは1つだけですか?

使用しているLoaderManagerを変更する方法を教えていただけたら、ボーナスポイントを教えてください。私のアクティビティのすべてのフラグメントに同じLoaderManagerを使用したい場合(それらのうちのいくつかは同じデータを取得していて、ローダーを共有するのがうまくいくでしょう)、それは可能ですか?

+3

[** LoaderManager(パート2)の理解**](http://www.androiddesignpatterns.com/2012/05/why-you-should-use-loadermanager.html) –

答えて

8

私は現在、アプリケーションをアンドロイド互換パッケージ(主にCursorLoaderとFragments用)に移植しています。私は現在、2つのフラグメント間でCursorLoaderを共有して、ContentProviderにクエリをスペアすることを試みています。私の世界へようこそ! ;)

単純なユースケース:

- DummyActivityはFragmentActivity/Log.dを拡張(Constants.LOGTAG、 "DummyActivity.onCreate" + getSupportLoaderManager()のtoString())。

- DataFragment extends Fragmentは、LoaderManager.LoaderCallbacks/Log.d(Constants.LOGTAG、 "DataFragment.onCreate" + getLoaderManager()。toString())を実装しています。

- ReportFragment extends Fragmentは、LoaderManager.LoaderCallbacks/Log.d(Constants.LOGTAG、 "ReportFragment.onCreate" + getLoaderManager()。toString())を実装しています。

DummyActivityはDataFragmentをインスタンス化し、後でReportFragmentをインスタンス化します。 logcat出力には、各LoaderManagerの異なるアドレスが表示されます。最初の結論として、各フラグメントは適切なLoaderManagerを持っているようです...

あなたの(私たちの))質問に答えることができれば、私は継続して更新します。進んだ場合は、貴重な知識を共有してください。

更新:

私の仮定は、ローダIDは断片のみに関連付けられる複数のローカルローダーを有効にするには、特定のフラグメントのためLoaderManagerのローカルスコープに関連付けられていることを(あなたが返すことができますid int argとinitLoader呼び出しに基づいてonCreateLoader内の別のローダー)。

は、これまでのところ私は、ローダー(...かどうかを)「再利用」するために管理:

- まず、私はDummyActivity onCreate方法でgetSupportLoaderManager().enableDebugLogging(true);でLoaderManagerのデバッグを有効にしています。

- 私はを、onCreateのDataFragmentとReportFragmentの両方のメソッドから呼び出しました。

- DataFragmentは、onCreateLoaderメソッドで作成されたCursorLoaderを、mCursorLoaderプライベートメンバーのセッターを介して公開します。

- ReportFragment onCreateLoaderは、(フラグメントをfindFragmentByTagで取得した後に)DataFragment CursorLoaderを返します。

フィルター(とやや難読化)logcat出力:

 DummyApp D DummyActivity.onCreate 
     DummyApp D DataFragment.newInstance 
     DummyApp D ReportFragment.newInstance 
     DummyApp D DataFragment.onCreate 
LoaderManager V initLoader in LoaderManager{405a19d0 in SpecificAction{4059ee98}}: args=null 
     DummyApp D DataFragment.onCreateLoader 
LoaderManager V Created new loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}} 
     DummyApp D DataFragment.onCreate 
     DummyApp D DataFragment.onActivityCreated 
     DummyApp D ReportFragment.onCreate 
LoaderManager V initLoader in LoaderManager{405a19d0 in DummyActivity{4059ee98}}: args=null 
LoaderManager V Re-using existing loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}} 
     DummyApp D SpecificActionReportFragment.onCreate 
     DummyApp D SpecificActionReportFragment.onActivityCreated 
LoaderManager V Starting in LoaderManager{405a19d0 in DummyActivity{4059ee98}} 
LoaderManager V Starting: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}} 
DummyProvider D query called 
DummyProvider D […]  
DummyProvider D [end of query] 
LoaderManager V onLoadComplete: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}} 
LoaderManager V onLoadFinished in CursorLoader{405a22e0 id=78}: CursorWrapperInner{405afb20} 
     DummyApp D ReportFragment.onLoadFinished 
     DummyApp D ReportFragment.displayActionReport 
     DummyApp D DummyActivity.setReportViewsVisibility 
     DummyApp D ReportFragment.setSaveReportImageViewVisibility 

2つの断片を説明したユースケースと異なる(DummyActivity onCreate方法から追加されたが、それは私たちが取り組んでいる問題には何も変更されていません)。残念ながら、ローダーはを最新のフラグメント(ここではReportFragment)に再割り当てされた...であり、DataFragment.onLoadFinishedは呼び出されません。したがって、このクラスのonLoadFinishedから更新が呼び出されたため、ReportFragmentは良好に見えますが、DataFragmentは最新ではありません。

私はCursorLoaderでのレジスタ呼び出しの基礎となる登録解除呼び出しがあると仮定します。

続ける...

+0

ありがとうございました!私はいくつかのiOSのことをしてきましたが、周りを遊んで1週間ほどでこの質問に答える時間があります。報告する! :) – num1

+0

私の仲間が待っているので、私は次の日もそれに取り組んでいます。 – Renaud

+0

私は最終的に私のContentProviderを最適化します。ボーナスポイントに値するとは申し訳ありません;) – Renaud

0

はい。それは私のために働いた。私は同じデータが異なるListViewに配置されているナビゲーションドロワーに3つの異なるフラグメントを持っています。 (すべてのフラグメントは同じアクティビティの一部です)。

マイAsyncTaskLoader:

public class MyTaskLoader extends AsyncTaskLoader<HashMap<String, Integer>> { 

public MyTaskLoader(Context context) { 
    super(context); 
} 

@Override 
public HashMap<String, Integer> loadInBackground() { 
... 
return hashMap; 
} 

... 
} 

は、すべてのフラグメントで同じローダーIDを使用します。

Fragment1:

public class Fragment1 extends BaseFragment implements LoaderManager.LoaderCallbacks<HashMap<String, Integer>> { 
@Override 
public void onCreate(Bundle savedInstanceState) { 

//initialize adapter 

getActivity().getSupportLoaderManager().initLoader(0, null, this); 

} 

@Override 
public Loader<HashMap<String, Integer>> onCreateLoader(int arg0, Bundle arg1) { 
    // TODO Auto-generated method stub 

    return new MyTaskLoader(getActivity()); 
} 

@Override 
public void onLoadFinished(Loader<HashMap<String, Integer>> arg0, 
     HashMap<String, Integer> data) { 
    // TODO Auto-generated method stub 

    listAdapter.setData(data.keySet()); 

} 

@Override 
public void onLoaderReset(Loader<HashMap<String, Integer>> arg0) { 
    // TODO Auto-generated method stub 

    listAdapter.setData(null); 
} 
} 

はFragment2に同じIDを使用:

public class Fragment2 extends BaseFragment implements LoaderManager.LoaderCallbacks<HashMap<String, Integer>> { 
@Override 
public void onCreate(Bundle savedInstanceState) { 

//initialize adapter 

getActivity().getSupportLoaderManager().initLoader(0, null, this); 

} 

@Override 
public Loader<HashMap<String, Integer>> onCreateLoader(int arg0, Bundle arg1) { 
    // TODO Auto-generated method stub 

    return new MyTaskLoader(getActivity()); 
} 

@Override 
public void onLoadFinished(Loader<HashMap<String, Integer>> arg0, 
     HashMap<String, Integer> data) { 
    // TODO Auto-generated method stub 

    listAdapter.setData(data.keySet()); 

} 

@Override 
public void onLoaderReset(Loader<HashMap<String, Integer>> arg0) { 
    // TODO Auto-generated method stub 

    listAdapter.setData(null); 
} 
} 

アダプタは、ローダを初期化する前に初期化する必要があります。 これまでのところ動作します。 しかし、これは正しい方法ですか?複数のフラグメントに共通のローダーを使用するより良い方法はありますか?

関連する問題