16

LoaderManager でローダーを識別するときは、一意の ID を使用します。これらのIDがどれだけ一意でなければならないかについて尋ねています。

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

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

4

2 に答える 2

8

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

簡単な使用例:

− DummyActivity は FragmentActivity / Log.d(Constants.LOGTAG, "DummyActivity.onCreate " + getSupportLoaderManager().toString()); を拡張します。

− DataFragment extends Fragment implement LoaderManager.LoaderCallbacks / Log.d(Constants.LOGTAG, "DataFragment.onCreate " + getLoaderManager().toString());

− ReportFragment extends Fragment implement LoaderManager.LoaderCallbacks / Log.d(Constants.LOGTAG, "ReportFragment.onCreate " + getLoaderManager().toString());

DummyActivity は DataFragment をインスタンス化し、後で ReportFragment をインスタンス化します。logcat の出力には、LoaderManager ごとに異なるアドレスが表示されます。最初の結論として、各 Fragment には適切な LoaderManager があるようです…</p>

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

アップデート:

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

これまでのところ、ローダーを「再利用」することができました(…かどうか):

− まず、getSupportLoaderManager().enableDebugLogging(true);DummyActivityonCreateメソッドで LoaderManager のデバッグを有効にしました。

− 次に、DataFragment と ReportFragment の両方getActivity().getSupportLoaderManager().initLoader(78, null, this);のメソッドから呼び出しました。onCreate

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

− ReportFragmentonCreateLoaderは DataFragment CursorLoader を返します ( で Fragment を取得した後findFragmentByTag)。

フィルタリングされた (そして少し難読化された) 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 つのフラグメントは、DummyActivityonCreateメソッドから追加されます (説明されているユース ケースとは異なりますが、私たちが取り組んでいる問題には何も変わりません)。残念ながら、ローダーはそれを呼び出す最新のフラグメント (ここでは ReportFragment) に再割り当てされ、DataFragment.onLoadFinished は呼び出されません。その結果、ReportFragment は問題ないように見えますが、更新がonLoadFinishedこのクラスの から呼び出されるため、DataFragment は最新ではありません。

CursorLoader で基になる unregister 呼び出しがあり、次に register 呼び出しがあると仮定します。

つづく…</p>

于 2011-09-29T23:13:59.620 に答える
0

はい。それは私のために働いた。Navigation Drawer に 3 つの異なる Fragment があり、同じデータが異なる ListView に取り込まれています。(すべてのフラグメントは同じアクティビティの一部です)。

私の AsyncTaskLoader:

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

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

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

...
}

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

フラグメント 1:

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);
}
}

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

于 2015-01-06T05:47:56.807 に答える