[Android]思考停止で使っていたFragmentを少し掘り下げる


粋がりのFragment

最初は、Activityにだけ処理を書いていた自分も、いつからかFragmentも使うようになりました。
ちょっとAndroid詳しくなっちゃった感じ?
と、肩に風を切るように開発を進めていますが、正直、Fragmentのことをそんなにわかっていません。
ということで、掘り下げていきましょう。

Fragmentとは?

Fragment は、FragmentActivity でのユーザー インターフェースの挙動や部位を表すものです。

相変わらず、ドキュメント先輩の威圧感半端ない。
何を言っているのか、ぱっと見わかりにくいです。

1 つのアクティビティに複数のフラグメントを組み合わせてマルチペイン UI をビルドしたり、複数のアクティビティでフラグメントを再利用したりできます。

簡単に説明すると、Fragmentとは、「ピース」(パズルのね)みたいな画面です。
Activityという、画面の「枠」にはめて使います。

フラグメントとは、アクティビティのモジュラー セクションのようなもので、独自のライフサイクルを持ち、独自の入力イベントを受信します。

Fragmentにも、Activityと同じようにライフサイクルがあるみたいです。

フラグメントはアクティビティの実行中に追加したり削除したりできます(別のアクティビティで再利用できる「サブ アクティビティ」のようなものです)。

どのActivityという「枠」だろうが、Fragmentという「ピース」をはめ込んでは、外すことができるという意味ですね。

フラグメントは常にアクティビティでホストされている必要があり、フラグメントのライフサイクルはホストのアクティビティのライフサイクルの影響を直接受けます。たとえば、アクティビティが一時停止しているとき、その中のすべてのフラグメントも一時停止し、アクティビティが破棄されると、すべてのフラグメントも破棄されます。

うんうん!
こっちの方が、「枠」と「ピース」の関係性がよく表現されていますね。
「枠」が破棄されたら、「ピース」も同じように破棄されますからね。

ただし、アクティビティの実行中(ライフサイクルで再開された状態)は、追加や削除といった操作を各フラグメントで独立して行うことができます。

Activityという「枠」が、あればFragmentという「ピース」を自由に生成(onCreateView),破棄(onDetach)できるというわけです。

フラグメントのトランザクションを実行するとき、アクティビティで管理されているバックスタックにそれを追加することもできます。アクティビティの各バックスタック エントリは、発生したフラグメントのトランザクションの記録です。バックスタックでは、[戻る] ボタンを押すとフラグメントのトランザクションを戻す(前に戻る)ことができます。

Activityには、バックスタックという「後入先出」の「まとめ処理」として記録していてくれてます。
つまり、aFragment -> bFragment -> cFragment
と、遷移したとき、戻るボタンをぽちぽち押すと、
cFragment -> bFragment -> aFragment
と戻ることができるわけです。

Fragment誕生秘話

どうして、このような画面が生まれたのでしょうか?

Android では、タブレットなどの大画面でのよりダイナミックで柔軟な UI デザインに対応するため、Android 3.0(API レベル 11)でフラグメントが採用されました。

ふむふむ。

たとえばニュース アプリケーションでは、1 つのフラグメントを使って左側に記事の一覧を表示し、別のフラグメントを使って右側に記事の内容を表示できます。両方のフラグメントが 1 つのアクティビティに横並びに表示され、それぞれのフラグメントには自身のライフサイクル コールバック メソッドがあり、それぞれのユーザー入力イベントを処理します。つまり、1 つのアクティビティで記事を選択して、別のアクティビティで記事を閲覧するのではなく、図 1 のタブレットのレイアウトのように 1 つのアクティビティ内で記事を選択して閲覧できるようになります。

ほー。
確かに、ipadでLINEやるとこんな感じの画面構成だよね。
左側にトーク一覧があって、右側にトーク画面があるみたいな。
タブレットでの有意義な画面構成を目的として生まれたっぽいですね。

各フラグメントは独自のライフサイクル コールバックを使用して自身のレイアウトと挙動とを定義するため、1 つのフラグメントを複数のアクティビティに含めることができます。このことから、再利用可能なデザインを用いることに加えて、1 つのフラグメントを他のフラグメントから直接操作しないようにする必要があります。

Activityという「枠」があれば、自由にFragmentという「ピース」を当てはめることができるので、競合が起きないように注意ってことですね。

引き続きニュース アプリケーションの例を使うと、アプリケーションがタブレット サイズの端末で実行中は、2 つのフラグメントをアクティビティ A に埋め込むことができます。しかし、ハンドセット サイズの画面では両方のフラグメントを表示する領域が足りないため、アクティビティ A には記事の一覧のフラグメントだけが含まれます。ユーザーが記事を選択すると、記事を閲覧するための 2 つ目のフラグメントが含まれるアクティビティ B が開始されます。そのため、アプリケーションは図 1 のようにフラグメントを異なる組み合わせで再利用することで、タブレットとハンドセットの両方に対応できるようになります。

タブレットの場合、画面サイズ、つまり「枠」に余裕があるので、二つの「ピース」をはめることができると。
逆に、スマホサイズだと一つというわけか。
面白いなぁ。
つまり、LINEの画面はFragmentで遷移している感じなのね。

終わりに

一旦ここまでにします。
Activityという「枠」にはめるFragmentという「ピース」という説明しかしてないと思いますが笑。
機会があれば、FragmentManagerとライフサイクルについても深掘りできたらと思います。