It’s now or never

IT系の技術ブログです。気になったこと、勉強したことを備忘録的にまとめて行きます。

【Android】Fragmentを使ってみる

Fragment は Android 3.0 ( API レベル "Honeycomb" ) から使用できるようになったコンポーネントです。
Fragmentを使用することで、一つのActivityに対して複数のUIを構築することが可能で、
画面の一部に対してのUI切り替えや遷移などを柔軟に行うことができます。

Fragmentの実装

Fragmentを実装するには、最低限、以下のメソッドを実装する必要があります。

Activityの状態 Fragmentで呼ばれるコールバック
onCreate() システムが、Fragmentを作成したときに呼び出される。
コンポーネントの初期化処理などをここで行う。
onCreateView() FragmentのUIが描画されるタイミングでよびだされる。
FragmentのレイアウトのRootになっているViewをここでinflateする。
onPause() Fragmentが停止するときによばれる。
Fragmentで変更されたステータスの保存はここで行う。

他にも様々なライフサイクルメソッドが存在しますが、今回は割愛します。

Fragmentに対してlayoutを紐付けるには、以下のようにonCreateView()でinflateを行います。

public class SampleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.sample_fragmet, container, false);
    }
}

Fragmentの表示方法

Activityから、Fragmentを表示するためには、FragmentManagerを使用します。
Fragmentの追加・削除・交換などのアクションは、FragmentTransactionによってコミット単位で管理されており、FragmentManagerから取得できるFragmentTransactionに対して、
各アクションを適用することで、Fragmentの管理を行うことが可能です。

新規で作成したFragmentの表示を行うためには以下のように記載します。
表示したいViewGroupに対して、Fragmentをadd()メソッドにより追加し
最後にcommit()を呼び出すことで対象のFragmentを表示することができます。

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        
FirstFragment fragment = new FirstFragment();
fragmentTransaction.add(R.id.fragment_container, fragment, "tag");
fragmentTransaction.commit();

Fragmentをバックスタックに追加する

FragmentをFragmentTransactionのバックスタックに追加することで、
スタック管理を行うことができます。

バックスタックはActivityにより管理されており、
ユーザがBACKキーを押すことにより前のFragmentへ戻ることが可能です。

以下は、表示中のFragmentを新しいFragmentと入れ替えるサンプルです。
addToBackStack(null)を呼び出すことにより元のFragmentをバックスタックへ追加しています。

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        
SecondFragment secondFragment = new SecondFragment();
fragmentTransaction.replace(R.id.fragment_container, secondFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

Fragment生成時の注意事項

Fragmentの生成処理は、一般的に下記のようなstaticメソッドが使用されます。

public static SampleFragment newInstance(int index) {
    SampleFragment f = new SampleFragment();

    Bundle args = new Bundle();
    args.putInt("index", index);
    f.setArguments(args);

    return f;
}

これは、システムがFragmentの再生成を行うときに、デフォルトのコンストラクタが呼ばれる為、
独自のコンストラクタを使用したパラメタの引き渡しができないという理由からです。

システムは、例えばメモリ不足などで破棄されたFragmentを再生成する時に、 Fragment#instantiate(Context context, String fname, Bundle args)) メソッドを使用します。
このメソッドは、引数で渡されたクラス名(fname)のFragmentを標準コンストラクタで呼び出してインスタンスを生成したのち、第3引数でセットしたBundleをsetArguments()でセットしてから返します。

そのため、Fragment生成に必要な引数がある場合は、 初期化時にsetArguments()を使用してパラメタを渡す必要があります。

ライフサイクル

Fragmentのライフサイクルは、Activityに似たつくりになっています。 FragmentはActivityによって保持されているため、お互いのライフサイクルは連動していて、 例えば、ActivityがonPause()を受け取ると、ActivityのそれぞれのFragmentはonPause()を受け取ります。

Activityの状態とFragmentのコールバックメソッドの関連

Activityの状態 Fragmentで呼ばれるコールバック
create OnAttach

OnCreate()

OnCreateView()

OnActivityCreated()
start OnStart()
resume OnResume()
pause OnPause()
stop OnStop()
destroyed OnDestroyView()

OnDestroy()

OnDetach()

参考

https://sites.google.com/a/techdoctranslator.com/jp/android/guide/activities/fragments