アンドロイドのフラグメントのライフサイクル
今日は、Androidフラグメントのライフサイクルについて学び、Androidアプリケーション内の2つのフラグメントから構成される1つのアクティビティクラスを実装します。
アンドロイドのフラグメント
AndroidのFragmentクラスは、動的なユーザーインターフェースを構築するために使用されます。FragmentはActivity内部で使用するべきです。Fragmentの最大の利点は、複数の画面サイズに対応したUIを簡単に作成できることです。1つのActivityには任意の数のFragmentを含めることができます。AndroidのFragmentはViewクラスのサブクラスではなく、他のほとんどのUIコンポーネントとは異なります。代わりに、Fragment内にViewが存在します。このViewが最終的にFragmentが存在するActivity内に表示されます。AndroidのFragmentはViewではないため、View(例:TextView)を追加するときとは少し異なる方法でActivityに追加されます。FragmentはActivity内のViewGroupに追加されます。FragmentのViewはこのViewGroup内に表示されます。以下の図は、FragmentがActivityに追加されるときに何が起こるかを示しています。最初にActivityはFragmentへの参照を取得します。次に、FragmentのViewがレンダリングされるViewGroupへの参照を取得します。そして、ActivityはFragmentを追加します。その後、Fragmentは自身のViewを作成し、Activityに返します。Viewは親のViewGroupに挿入され、Fragmentは起動されます。
フラグメントのライフサイクル
以下の画像でAndroidフラグメントのライフサイクルが説明されています。下記にはフラグメントのライフサイクルのメソッドがあります。
-
- onAttach(アタッチ)メソッド:このメソッドは、onCreate()よりも前に呼び出されます。フラグメントがアクティビティにアタッチされたことを知らせるために使用されます。このメソッドには、フラグメントのホストとなるアクティビティが渡されます。
-
- onCreateView(ビューを作成する)メソッド:システムは、最初にフラグメントがUIを描画する必要がある時にこのコールバックを呼び出します。フラグメントのUIを描画するためには、このメソッドからViewコンポーネントを返す必要があります。フラグメントがUIを提供しない場合は、nullを返すこともできます。
-
- onViewCreated(ビューが作成された)メソッド:onCreateView()の後に呼び出されます。特に、onCreateView()の実装を継承している場合に便利ですが、リストフラグメントのような場合やアダプターの設定が必要な場合に使用されます。
-
- onActivityCreated(アクティビティが作成された)メソッド:onCreate()とonCreateView()の後に呼び出され、アクティビティのonCreate()が完了したことを示します。フラグメント内で初期化が必要なアクティビティの作業に依存するものがある場合は、このメソッドを使用して初期化を行うことができます。
-
- onStart(開始)メソッド:フラグメントが表示された時に一度呼び出されます。
-
- onPause(一時停止)メソッド:ユーザーがフラグメントから出る最初の兆候としてシステムがこのメソッドを呼び出します。現在のユーザーセッションを超えて永続化する必要のある変更をコミットするのに通常このメソッドを使用します。
-
- onStop(停止)メソッド:onStop()を呼び出すことで、フラグメントが停止されます。
-
- onDestroyView(ビューの破棄)メソッド:onDestroy()の前に呼び出されます。UIの設定を行うonCreateView()の対応部分です。UIに固有のクリーンアップが必要な場合は、このメソッドにロジックを記述することができます。
-
- onDestroy(破棄)メソッド:フラグメントの状態を最終的にクリーンアップするためにonDestroy()が呼び出されますが、Androidプラットフォームによって呼び出されることは保証されません。
- onDetach(デタッチ)メソッド:onDestroy()後に呼び出され、フラグメントがホストアクティビティから切り離されたことを知らせます。
アンドロイドのフラグメントクラス
ハニーコム(API 11)では、Android APIにフラグメントが追加されました。
-
- android.app.Fragment: すべてのフラグメント定義の基本クラスです。
-
- android.app.FragmentManager: アクティビティ内のフラグメントオブジェクトと対話するためのクラスです。
-
- android.app.FragmentTransaction: フラグメント操作の一連のアトミックなセットを実行するためのクラスです。
- Googleが提供する互換パッケージライブラリを使用する場合、以下のクラスが実装に使用されます。
- android.support.v4.app.FragmentActivity : The base class for all activities using compatibility-based fragment (and loader) features
- android.support.v4.app.Fragment
- android.support.v4.app.FragmentManager
- android.support.v4.app.FragmentTransaction
AndroidフラグメントのonCreateView()
以下は、onCreateView()を利用した実装例の一部です。
public class SampleFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parentViewGroup,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_sample, parentViewGroup, false);
return rootView;
}
}
onCreateView()メソッドは、LayoutInflater、ViewGroup、およびBundleをパラメータとして取得します。LayoutInflaterは、レイアウトXMLファイルに基づいてViewインスタンスを作成できるコンポーネントです。例では、layout.inflate()を呼び出すことによって実際にその動作を行っています。inflate()メソッドは、3つのパラメータを取ります:レイアウトXMLファイルのID(R.layout内)、フラグメントのViewが挿入される親ViewGroup、レイアウトXMLファイルからインフレートされたフラグメントのViewが親ViewGroupに挿入されるかどうかを示す真偽値の3番目のパラメータです。この場合、フラグメントのViewは別の場所でAndroidコードによって親ViewGroupにアタッチされるため、falseを渡します。inflate()の最後のパラメータとしてfalseを渡すと、親ViewGroupはインフレートされたViewのレイアウト計算に使用されるため、親ViewGroupにnullを渡すことはできません。onCreateView()のViewGroupパラメータは、フラグメントのViewが挿入される親ViewGroupです。これは、フラグメントを「ホスト」するアクティビティ内のViewGroupです。onCreateView()のBundleパラメータは、フラグメントがデータを保存できるBundleです。これはアクティビティと同様です。
Androidフラグメントの例
Androidフラグメントのサンプルプロジェクトは、TextFragmentとMenuFragmentの2つのフラグメントを持つ単一のアクティビティで構成されています。
アンドロイドフラグメントの例示コード
MainActivityは、TextFragmentとMenuFragmentの2つのフラグメントを保持しています。では、activity_main.xmlのXMLレイアウトでフラグメントを定義することから始めましょう。
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1.0">
<fragment
android:layout_height="match_parent"
android:layout_width="match_parent"
class="scdev.com.fragments.fragments.MenuFragment"
android:id="@+id/fragment"
android:layout_weight="0.5"/>
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
class="scdev.com.fragments.fragments.TextFragment"
android:id="@+id/fragment2"
android:layout_weight="0.5"/>
</LinearLayout>
このアクティビティに属するフラグメントのクラスファイルは、 class=”scdev.com.fragments.fragments.TextFragment” として定義されています。以下のスニペットに示すように、フラグメントクラスとそのレイアウトが定義されています。
package scdev.com.fragments.fragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import scdev.com.fragments.R;
public class TextFragment extends Fragment {
TextView text,vers;
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.text_fragment, container, false);
text= (TextView) view.findViewById(R.id.AndroidOs);
vers= (TextView)view.findViewById(R.id.Version);
return view;
}
public void change(String txt, String txt1){
text.setText(txt);
vers.setText(txt1);
}
}
テキストフラグメント.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:gravity="center"
android:background="#5ba4e5"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40px"
android:textColor="#ffffff"
android:layout_gravity="center"
android:id="@+id/AndroidOs"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:textSize="30px"
android:id="@+id/Version"/>
</LinearLayout>
TextFragmentには、Androidバージョン名と番号を表示するテキストビューが含まれています。
package scdev.com.fragments.fragments;
import android.app.ListFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import scdev.com.fragments.R;
public class MenuFragment extends ListFragment {
String[] AndroidOS = new String[] { "Cupcake","Donut","Eclair","Froyo","Gingerbread","Honeycomb","Ice Cream SandWich","Jelly Bean","KitKat" };
String[] Version = new String[]{"1.5","1.6","2.0-2.1","2.2","2.3","3.0-3.2","4.0","4.1-4.3","4.4"};
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.list_fragment, container, false);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, AndroidOS);
setListAdapter(adapter);
return view;
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
TextFragment txt = (TextFragment)getFragmentManager().findFragmentById(R.id.fragment2);
txt.change(AndroidOS[position],"Version : "+Version[position]);
getListView().setSelector(android.R.color.holo_blue_dark);
}
}
リスト_フラグメント.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@android:id/list" />
</LinearLayout>
MenuFragmentはListViewを表示します。ここで示されているように、ListViewのレイアウトはデフォルトのsimple_list_item_1であり、前の記事で作成したカスタムレイアウトとは異なります。MainActivityはonCreateメソッドからsetContentViewを呼び出します。フラグメントはxmlファイルから呼び出されます。または、以下のスニペットに示すように、アクティビティクラスからFragmentManagerを使用してフラグメントを追加することもできます。
getFragmentManager()
.beginTransaction()
.add(R.id.fragmentParentViewGroup, new MyFragment())
.commit();
次に示すFrameLayoutに所属するidフラグメントParentViewGroupがここにあります。
<FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:id="@+id/fragmentParentViewGroup"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MyActivity"
tools:ignore="MergeRootFrame" />
アンドロイドのフラグメントの例を持つアプリ
以下は、私たちのプロジェクトが生成した出力を示しており、ここには2つのフラグメントが存在しています。左側のフラグメントからいずれかを選択すると、右側のフラグメントにデータが表示されます。最終的なAndroidフラグメントプロジェクトは、以下のリンクからダウンロードできます。
アンドロイドフラグメントプロジェクトをダウンロードしてください。