Android碎片的生命周期
今天我们将学习Android片段生命周期,并在Android应用程序中实现一个包含两个片段的单一活动类。
安卓的碎片
Android中的Fragment类用于构建动态用户界面。Fragment应该在Activity中使用。Fragment的最大优点是简化了为多种屏幕尺寸创建用户界面的任务。一个Activity可以包含任意数量的Fragment。Android的Fragment本身不是View的子类,而大多数其他UI组件是View的子类。相反,Fragment内部有一个视图。最终,这个视图将在Fragment所在的Activity中显示出来。由于Android的Fragment不是一个View,所以将其添加到Activity中的方法与添加View(例如TextView)有所不同。Fragment被添加到Activity内的ViewGroup中。Fragment的视图显示在这个ViewGroup内。以下图例展示了当Fragment被添加到Activity中时发生的情况:首先,Activity获取对Fragment的引用。然后,它获取对将渲染Fragment视图的ViewGroup的引用。然后Activity添加Fragment。接着,Fragment创建它的视图并将其返回给Activity。视图然后被插入到ViewGroup父容器中,Fragment就开始运行了。
碎片生命周期
以下图片展示了Android fragment的生命周期。下面是fragment生命周期的方法。
-
- onAttach() :此方法将首先被调用,甚至在onCreate()之前,让我们知道你的fragment已经与activity关联了起来。你会被传递你的fragment所属的activity。
-
- onCreateView() :系统在fragment第一次绘制其UI时调用此回调方法。为了绘制fragment的UI,必须从此方法返回一个View组件,该组件是fragment布局的根部。如果fragment不提供UI,则可以返回null。
-
- onViewCreated() :此方法将在onCreateView()之后被调用。当继承了onCreateView()的实现但需要配置结果视图时,这将非常有用。例如,使用ListFragment时设置适配器。
-
- onActivityCreated() :此方法在onCreate()和onCreateView()之后被调用,指示activity的onCreate()已完成。如果fragment中有些东西依赖于activity的onCreate()已完成的工作来进行初始化,则可以使用onActivityCreated()进行初始化工作。
-
- onStart() :一旦fragment变得可见,将调用onStart()方法。
-
- onPause() :系统将此方法作为用户离开fragment的第一个迹象调用。通常,在此处应提交任何需要在当前用户会话之外持久保存的更改。
-
- onStop() :通过调用onStop()方法使fragment停止。
-
- onDestroyView() :它在onDestroy()之前被调用。这是onCreateView()的对应方法,在此方法中我们设置UI。如果有一些需要根据UI特定清理的东西,可以将该逻辑放在onDestroyView()中。
-
- onDestroy() :调用onDestroy()以对fragment的状态进行最终清理,但Android平台不保证会调用此方法。
- onDetach() :它在onDestroy()之后被调用,用于通知fragment与其托管的activity已经解除关联。
Android的Fragment类
在Honeycomb(API 11)中,Android API 增加了片段。
-
- android.app.Fragment:所有片段定义的基类
-
- android.app.FragmentManager:在活动中与片段对象进行交互的类
-
- android.app.FragmentTransaction:执行一组片段操作的类
- 使用谷歌提供的兼容包库时,可以使用以下类来进行实现。
- 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 Fragment的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()方法接受三个参数:布局XML文件的ID(在R.layout内),要将片段的View插入其中的父ViewGroup,以及一个布尔值,用于指示是否将从布局XML文件中膨胀的片段的View插入到父ViewGroup中。在这种情况下,我们将传递false,因为View将通过我们调用的一些Android代码附加到父ViewGroup中的其他位置。当您将false作为inflate()的最后一个参数传递时,父ViewGroup仍然用于膨胀View的布局计算,因此不能将null作为父ViewGroup传递。onCreateView()的ViewGroup参数是要将片段的View插入其中的父ViewGroup。这是活动中的一个ViewGroup,将“托管”片段。onCreateView()的Bundle参数是一个Bundle,片段可以在其中保存数据,就像在Activity中一样。
Android碎片示例
Android碎片示例项目由一个活动组成,该活动分别包含两个碎片:TextFragment和MenuFragment。
Android Fragment 示例代码
MainActivity包含了两个片段TextFragment和MenuFragment。因此,让我们开始使用xml布局activity_main.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包括两个TextView,分别显示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,与我们在之前的文章中为 ListView 创建的自定义布局相对应。MainActivity 通过调用 onCreate 方法中的 setContentView 方法来调用它。片段是从 xml 文件中调用的。或者,我们可以通过使用 FragmentManager 从活动类中添加片段,如下面的片段所示:
getFragmentManager()
.beginTransaction()
.add(R.id.fragmentParentViewGroup, new MyFragment())
.commit();
以下示例中,id fragmentParentViewGroup 属于下方显示的 FrameLayout。
<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" />
Android碎片示例应用
以下显示了我们项目生成的输出,您可以看到此处存在两个片段,当您在左侧片段中选择任意一个时,数据将填充到右侧片段中。您可以从下面的链接下载最终的Android片段项目。
下载Android碎片项目