画面間でデータを受け渡ししたいと思うことはよくあると思います。その方法を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);
}
画面間でのデータ渡しについて、少しは参考になったでしょうか(^^)