FragmentManager.putFragment

FragmentManager.putFragmentで、Fragmentの参照を一応保存できる。

FragmentManager  |  Android Developers

strings.xmlで、

Activity用の"Button1"と、Fragment用の"FButton1"と、TextViewの"Fragment1"。
fragment1_main.xmlは、

TextViewとButton。
activity_main.xmlは、

ButtonとFrameLayout。
Fragment1.javaは、

インスタンスを保持出来てるかは、mNumberでチェックできる。
onCreateViewでTextViewにmNumberをセット。
Buttonを押すと、mNumberが増えてまたセット。
MainActivity.javaは、

MainActivity側のButtonでFragment1をadd。
onSaveInstanceStateの時に、putFragmentで保存、onRestoreInstanceStateの時に、getFragmentで復元。
回転すれば、ここに来るので、その時のIDとか、mNumberがどうなるか見てる。

起動時
起動時

起動時。
Button1を押すと、

Fragment1がadd
Fragment1がadd

Fragment1がadd。
FButton1を押すと、

0から1に増えている。押すたびに増える。
0から1に増えている。押すたびに増える。

0から1に増えている。押すたびに増える。
回転すると、

0に戻ってしまう
0に戻ってしまう

0に戻ってしまう。

ログを見るとわかるが、IDは同じなのに、インスタンスは別。
ログを見るとわかるが、IDは同じなのに、インスタンスは別。

ログを見るとわかるが、IDは同じなのに、インスタンスは別。
実際のところ、インスタンスが永続化されるわけではなく、同じIDで再生成しているだけみたいなので、オブジェクトもビューも同じ状態を維持できてるわけではない。
("一応"保存と言ってるのはそういうこと・・・。)

Sample/android/FragmentManager/putFragment/src/FragmentManager at master · bg1bgst333/Sample · GitHub

Fragment.getTargetRequestCode

Fragment.setTargetFragmentには、リクエストコードを指定することも出来た。
で、このリクエストコードは、Fragment.getTargetRequestCodeを使って取得できる。

Fragment  |  Android Developers

これとFragment.onActivityResultを使うことで、ターゲットへのキャストなしに、ターゲット側で処理が出来る。
リクエストコードを使う場合は、DialogFragmentの例が一般的。
Fragment1.javaは、

CustomDialogFragmentの表示で、自身のFragmentとしてthis、そしてリクエストコード123を渡す。
onActivityResultで、RESULT_OKなら、リクエストコードを表示。
リクエストコードが123なら、さらにメッセージを表示。
CustomDialogFragment.javaは、

OKなら、messageに"OK"を登録。
getTargetRequestCodeでリクエストコードrを取得し表示。
target.onActivityResultで、Fragment1のonActivityResultが呼ばれるようにしている。
NGの場合も、同じような感じになっている。

起動時
起動時

起動時。
Button1を押すと、

ダイアログが出る
ダイアログが出る

ダイアログが出る。
OKを押すと、

rが123
rが123

rが123。

onActivityResult側でも123
onActivityResult側でも123

onActivityResult側でも123。

messageは"OK"
messageは"OK"

messageは"OK"。

NGを押した場合も、requestCodeは同じで、messageは"NG"となる。
NGを押した場合も、requestCodeは同じで、messageは"NG"となる。

NGを押した場合も、requestCodeは同じで、messageは"NG"となる。

Sample/android/Fragment/getTargetRequestCode/src/Fragment at master · bg1bgst333/Sample · GitHub

Fragment.getTargetFragment

Fragment.getTargetFragmentで、登録したFragmentを取得できる。

Fragment  |  Android Developers

前回はaddだったので、Fragment1のインスタンスが残っている状態のため参照することが出来たが、replaceの場合はどうだろうか。
Fragment1.javaで、

addをreplaceに置き換える。
また、customMethodでgetActivityがnullかどうか調べる。
Fragment2.javaは、

targetFragmentが取得できるのかは念入りにチェックしないといけないし、その上でcustomMethodを呼ぶ。

起動時
起動時

起動時。
Button1を押すと、

replaceなので、今度は文字がダブつかない。
replaceなので、今度は文字がダブつかない。

replaceなので、今度は文字がダブつかない。
Button2を押すと、

予想に反して、targetFragmentはnullにならずに取得できる。
予想に反して、targetFragmentはnullにならずに取得できる。

予想に反して、targetFragmentはnullにならずに取得できる。

ただし、customMethodの中で、getActivityがnullになっている。
ただし、customMethodの中で、getActivityがnullになっている。

ただし、customMethodの中で、getActivityがnullになっている。
つまり、Fragment1のインスタンスは生きているが、Activityに紐づいておらず、取り外されたということかな。

Sample/android/Fragment/getTargetFragment/src/Fragment at master · bg1bgst333/Sample · GitHub

Fragment.setTargetFragment

FragmentからFragmentに通知したり、Fragmentから別のFragmentのメソッドを呼ぶのに、Fragment.setTargetFragmentを使って、あらかじめ自身のFragmentを登録しておくという処理をする。

Fragment  |  Android Developers

strings.xmlで、

TextViewとButton2個ずつ。
fragment1_main.xmlで、

TextViewとButtonを用意。
fragment2_main.xmlも、

同様。
activity_main.xmlは、

FrameLayoutだけ。
Fragment1.javaは、

Buttonを押されたら、Fragment2をadd。
Fragment2.newInstanceにthisを渡すようになっているのがポイント。
customMethodをFragment2から呼び出したい。
Fragment2.javaは、

newInstanceの中で引数のtargetをfragment2.setTargetFragmentで登録。
このtargetはFragment1だから、これを取り出せたら、Fragment1を操作できる。
Fragment2のButtonが押されたら、getTargetFragmentでtargetFragmentとして取り出すことが出来る。
Fragment1にキャストが必要なのが面倒だが、fragment1.customMethodを呼び出せる。
MainActivity.javaは、

起動時、Fragment1を追加。

起動時
起動時

起動時。
Button1を押すと、

Fragment2が上に被さる。(addなのでこうなっちゃう。)
Fragment2が上に被さる。(addなのでこうなっちゃう。)

Fragment2が上に被さる。(addなのでこうなっちゃう。)
今度はButton2を押すと、

customMethodを呼び出せた。
customMethodを呼び出せた。

customMethodを呼び出せた。

Sample/android/Fragment/setTargetFragment/src/Fragment at master · bg1bgst333/Sample · GitHub

Fragment.onActivityResult

Fragment.startActivityForResultの結果は、Fragment.onActivityResultで受け取る。

Fragment  |  Android Developers

MainActivity.javaは、

onActivityResultはあるけど、ここにはこない。
SubActivity.javaは、

messageとして"ABCDE"、そしてRESULT_OKをセット。
Fragment1.javaは、

Fragment.startActivityForResultでSubActivityを起動。
ここのonActivityResultで、resultCode、requestCodeを表示し、1ならmessageも表示。

最初
最初

最初。

Button押したらSubActivity
Button押したらSubActivity

Button押したらSubActivity。

戻ってくるとresultCodeが-1はRESULT_OK
戻ってくるとresultCodeが-1はRESULT_OK

戻ってくるとresultCodeが-1はRESULT_OK。

Fragmentとあるので、Fragment.onActivityResultだし、requestCodeは1になっている。
Fragmentとあるので、Fragment.onActivityResultだし、requestCodeは1になっている。

Fragmentとあるので、Fragment.onActivityResultだし、requestCodeは1になっている。

タイミング逃してうっすらだけど"ABCDE"も表示
タイミング逃してうっすらだけど"ABCDE"も表示

タイミング逃してうっすらだけど"ABCDE"も表示。

Sample/android/Fragment/onActivityResult/src/Fragment at master · bg1bgst333/Sample · GitHub

FragmentTransaction.hide

FragmentTransaction.hideは、Fragmentの非表示だけであり、削除はしない。

FragmentTransaction  |  Android Developers

なので、onDestroyやonDestroyViewなどのライフサイクルは発生しない。
FragmentTransaction.removeの項をベースに、

Buttonが押されたら、removeではなくhideを呼ぶ。

最初はこう
最初はこう

最初はこう。

この時のログはこう
この時のログはこう

この時のログはこう。

Buttonを押すと非表示になる
Buttonを押すと非表示になる

Buttonを押すと非表示になる。

onDestroyもonDestroyViewも呼ばれない
onDestroyもonDestroyViewも呼ばれない

onDestroyもonDestroyViewも呼ばれない。

Sample/android/FragmentTransaction/hide/src/FragmentTransaction at master · bg1bgst333/Sample · GitHub

Activity.onActivityResult

Activity.startActivityForResultでの処理結果は、Activity.onActivityResultで受け取る。

Activity  |  Android Developers

いまさらの感じあるけど、SampleのActivity.startActivityForResultの項をベースに、

SubActivityのButton押したら、RESULT_CANCELEDをセット。

MainActivityでは、RESULT_CANCELEDなら、"RESULT_CANCELED"とToast表示。

Buttonを押してSubActivityに
Buttonを押してSubActivityに

Buttonを押してSubActivityに。

こっちでもButtonを押すとMainActivityに戻る
こっちでもButtonを押すとMainActivityに戻る

こっちでもButtonを押すとMainActivityに戻る。

戻った時にこうなる
戻った時にこうなる

戻った時にこうなる。

Sample/android/Activity/onActivityResult/src/Activity at master · bg1bgst333/Sample · GitHub