基本的に同じデータの 2 つのビューがあります。
上記の両方は、ローダー パターンを使用して同じデータを取得しています ( LoaderCallbacks の拡張、ContentProviderのクエリなど)。
どちらも、ViewPager内の単一のアクティビティ内でホストされます。
これらのフラグメントの両方について、現在選択されているリスト項目/マーカーを同期するための最良の戦略は何ですか? (「マイ プレイス」編集 UI、または左側のペインと中央に地図がある Google マップの「ルート案内」を考えてみてください)。
これまでに考えているシナリオ:
- すべてのフラグメントが、コールバック インターフェイスを介して選択の変更について手動で相手に通知するようにします (これには、Android ドキュメントで提案されているように、フラグメント間通信を調整するための基になるアクティビティが含まれる可能性があります)。
- どういうわけか、両方のフラグメントが同じ Cursor または ListAdapter を使用するようにします (マップの意味は何であれ、カーソルから直接入力されるため)。
- (他の何か?)
誰かがこの正確なケースをすでに扱っているのではないでしょうか? (「車輪の再発明」を避けたかっただけです。あまりにも概念的な質問で申し訳ありません。)
編集(解決策)
私はMaciejが私の正確な質問(「最善の戦略」など..)に答えたと思うので、答えは1と2の両方です;-)
詳細に進むと、私の実装は次のようになりました。
最初は、Java でパブリッシャー/サブスクライバー パターンを処理する際の膨大なオーバーヘッド (インターフェイス、コールバックの適切な場所の検索など) に怯えました。幸いなことに、Ottoバスの実装が私の目に留まり、フラグメント間の通信が些細なことになりました。選択の変更についてすべてのサブスクライバーに通知できるだけでなく、Loader Patter 全体がうまく適合します。
Otto のサンプル コードから BusProvider クラスを借ります。
通知データを運ぶメッセージ コントラクトをいくつか作成します。
public class LocationSelectedEvent { public long id; } public class LocationsLoadedEvent { public Cursor cursor; }
@Subscribe を使用してフラグメント内の「レシーバー」メソッドに注釈を付けます (以下の例はローダーの場合で、選択変更の場合はそれほど複雑ではありません)。
@Subscribe public void onLoadFinished(LocationsLoadedEvent event) { final CursorAdapter a = (CursorAdapter) getListAdapter(); a.swapCursor(event.cursor); }
通知を「リッスン」するフラグメントを作成します。
@Override public void onActivityCreated(Bundle savedInstanceState) { BusProvider.getInstance().register(this); }
フラグメントが「生きていない」ときにリッスンを停止するようにします (特にフラグメント API に当てはまり、難しい方法で学習しました)。
@Override public void onDestroy() { super.onDestroy(); BusProvider.getInstance().unregister(this); }
最後に、必要に応じて通知をトリガーします (以下の例は、カーソルが読み込まれたときにLocationListアクティビティから通知する方法を示しています)。
@Override public void onResume() { if(null == getLoaderManager().getLoader(0)) { getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int paramInt, Bundle paramBundle) { return new CursorLoader(LocationsList.this, Locations.CONTENT_URI, null, null, null, null); } @Override public void onLoadFinished(Loader<Cursor> paramLoader, Cursor cursor) { BusProvider.getInstance().post(new LocationsLoadedEvent(cursor)); } @Override public void onLoaderReset(Loader<Cursor> paramLoader) { BusProvider.getInstance().post(new LocationsLoadedEvent(null)); } }); } super.onResume(); }
おまけ: 通知フローの視覚化