画面間でデータを受け渡ししたいと思うことはよくあると思います。その方法を4つ紹介します。
① Fragment Instance引数渡し
まずは、普通に使っているであろうものから。Fragmentとして画面を開く場合に下記のように new で開くと何も渡せません。
FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); Fragment fragment = new SampleFragment(); transaction.replace(R.id.content, fragment); transaction.addToBackStack(null); transaction.commit();
これを、次のように newInstance( param1, param2, param3 ) として開くことで、パラメータを渡すことができます。これによって、同じFragmentでも、状況に応じて異なる結果を表示させることができます。
FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); Fragment fragment = SampleFragment.newInstance( param1, param2, param3 ); transaction.replace(R.id.content, fragment); transaction.addToBackStack(null); transaction.commit();
② Intentによるbitmap渡し
ある画面でバックエンドからbitmapを取得したとします。クリックして、詳細データを表示するような画面構成の場合、クリック後の画像はどう準備したらよいでしょうか?バックエンドのパスを①のFragment Instance引数に渡し、再度バックエンドから取得することもできるでしょう。画像をローカルに保存しておき、そのパスを渡すことで、ローカルから取得することもできるでしょう。ここで紹介するのは、画像をBundleに入れて渡す方法です。この方法だとシンプルに渡すことができます
Bundle bundle = new Bundle(); Bitmap bmp = ((BitmapDrawable) {ImageView}.getDrawable()).getBitmap(); bundle.putParcelable("param", bmp);
{ImageView}←ここには、Bitmapを表示しているImageViewを指定します。上記は、すでにImageViewに表示されている画像を取得し、Bundleにつめて①のFragment Instance引数でbundleを渡すことができます。bitmapはParcelableというインタフェースを持っているので可能なのです。なお、Parcelable インタフェースをクラスにつけることで、クラスごと渡せたりするようです。org.parceler:parceler-apiを利用することで@Parcelというアノテーションを追加するだけで良いとのこと。素晴らしい。
③ コールバックリスナーで受け渡し、というか通知
呼び出し側でコールバックインタフェースを定義し、呼び出します。呼び出される側では、呼び出し側のインタフェースをimplemnetsし、インタフェースの実装を行います。こうすることで、インタフェースのパラメータを呼び出される側で使用できます。というか再描画してね、とか通知するのによく使います。
インタフェースの定義public interface OnOkClickListener { public void onOkClicked(Bundle args); }呼び出される側のコールバック関数参照設定
private OnOkClickListener mListener; mListener =(OnOkClickListener) {呼び出される側のfragment};コールバック関数の呼び出し
Bundle arg = new Bundle(); arg.putString("KEY", "SAMPLE"); arg.putInt("ITEM_KEY", 100); mListener.onOkClicked(arg);呼び出される側のコールバック関数参照設定
public void onOkClicked(Bundle args) { String str = args.getString("KEY"); switch (str){ case "SAMPLE": Integer sample = args.getInt("ITEM_KEY"); break; } }
④ onActivityResult
ActivityやDialogを呼び出した場合に、呼び出し先の処理完了時に戻りを取得することができます。ここでは、呼び出し元のFraと呼び出されるDialog間でのデータ受け渡しを説明します。この場合でもDialogの生成では①と同じくStaticなnewInstanceを呼び出します。この時、戻りを返すFragmentを渡すことが重要です。リクエストコードについては、識別できる任意の値にしておきましょう
public static SampleFragment newInstance(Fragment target, int requestCode, String param1, String param2, int param3) { SampleFragment fragment = new SampleFragment(); fragment.setTargetFragment(target, requestCode); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); args.putInt(ARG_PARAM3, param3); fragment.setArguments(args); return fragment; }
呼び出されたDialog側では、DialogのOKボタンクリック時に戻したいデータをIntentに詰め込み、呼び出し元のonActivityResultを呼び出します
Fragment target = getTargetFragment(); if (target == null) { return; } Intent data = new Intent(); data.putExtra(Intent.EXTRA_USER, hogehoge1); data.putExtra(Intent.EXTRA_TEXT, hogehoge2); data.putExtra(Intent.EXTRA_SUBJECT, hogehoge3); target.onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, data);
呼び出した側では、onActivityResultの実装を記述しておくことで、Dialogでの結果を利用することが可能になります
public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case 0: if (resultCode != Activity.RESULT_OK) { return; } // ここに処理を記述します return; } super.onActivityResult(requestCode, resultCode, data); }
画面間でのデータ渡しについて、少しは参考になったでしょうか(^^)