Android片段生命周期
今天,我们将学习Android Fragment Lifecycle,并在android应用程序中实现由两个片段组成的单个活动类。
Android片段
Android中的Fragment
类用于构建动态用户界面。
片段应在活动内使用。
片段的最大优点是,它简化了为多种屏幕尺寸创建UI的任务。
一个活动可以包含任意数量的片段。
Android片段本身并不是大多数其他UI组件都是View的子类。
相反,片段内部有一个视图。
该视图最终显示在片段所在的活动中。
由于android片段不是视图,因此将其添加到活动中看起来与添加视图(例如TextView)有所不同。
片段被添加到活动内部的ViewGroup中。
片段的视图显示在此ViewGroup中。
下图显示了将片段添加到活动时发生的情况:
首先,活动获得对该片段的引用。
然后,它获取对ViewGroup的引用,该片段的视图将其中呈现。
然后,活动添加片段。
然后,该片段创建其视图并将其返回到活动。
然后将视图插入到ViewGroup父级中,并且该片段处于活动状态。
片段生命周期
下图说明了Android片段的生命周期。
以下是片段生命周期的方法。
onAttach()
:即使在onCreate()之前,也会首先调用此方法,让我们知道您的片段已附加到活动中。
您通过了将托管您的片段的活动onCreateView():当片段第一次绘制其UI时,系统调用此回调。
要绘制片段的UI,必须从此方法返回View组件,该组件是片段布局的根。
如果片段不提供UI,我们可以返回nullonViewCreated():将在onCreateView()之后调用。
这在继承onCreateView()实现时特别有用,但是我们需要配置结果视图,例如使用ListFragment以及何时设置适配器onActivityCreated():将在onCreate()和onCreateView()之后调用,以指示活动的onCreate()已完成。
如果片段中需要初始化的内容取决于活动的onCreate()完成工作,则可以使用onActivityCreated()进行初始化工作onStart()
:一旦可见片段,就会调用onStart()方法onPause():系统调用此方法作为用户离开该片段的第一个指示。
通常,您应该在此处提交应保留在当前用户会话之后的所有更改。onStop()
:通过调用onStop()将片段停止onDestroyView()
:在onDestroy()之前调用。
这与设置UI的onCreateView()相对。
如果需要针对UI进行清理,则可以将该逻辑放在onDestroyView()中。onDestroy():onDestroy()被调用以对片段的状态进行最终清理,但不能保证由Android平台调用。
onDetach()
:在onDestroy()之后调用,以通知该片段已从其托管活动中取消关联
Android片段类
片段已添加到Honeycomb(API 11)中的Android API中。
android.app.Fragment
:所有片段定义的基类android.app.FragmentManager
:用于与活动内的片段对象进行交互的类- android.app.FragmentTransaction:用于执行片段操作的原子集的类
使用Google提供的兼容性软件包库时,以下类用于实现。
- android.support.v4.app.FragmentActivity:使用基于兼容性的片段(和加载程序)功能进行的所有活动的基类
- 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()方法采用三个参数:布局XML文件的ID(在R.layout内部),要插入片段的View的父ViewGroup,以及第三个布尔值,用于告知片段的View是否从布局XML文件应插入父级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片段示例代码
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="theitroad.local.fragments.fragments.MenuFragment" android:id="@+id/fragment" android:layout_weight="0.5" <fragment android:layout_width="match_parent" android:layout_height="match_parent" class="theitroad.local.fragments.fragments.TextFragment" android:id="@+id/fragment2" android:layout_weight="0.5" </LinearLayout>
我们可以看到,作为该活动一部分的片段的类文件被定义为class =" theitroad.local.fragments.fragments.TextFragment"
片段类及其布局的定义如下面的代码片段所示。
package theitroad.local.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 theitroad.local.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); } }
text_fragment.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 theitroad.local.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 theitroad.local.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); } }
list_fragment.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();
此处idfragmentParentViewGroup属于以下所示的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"