您的位置:首页 > 其它

Activity, Fragment生命周期

2015-12-11 15:42 260 查看
官网帮助文档链接:
http://developer.android.com/guide/components/fragments.html
主要看两张图,和跑代码

一,Fragment的生命周



二,与Activity生命周期的对比



场景演示 : 切换到该Fragment

11-29 14:26:35.095: D/AppListFragment(7649): onAttach

11-29 14:26:35.095: D/AppListFragment(7649): onCreate

11-29 14:26:35.095: D/AppListFragment(7649): onCreateView

11-29 14:26:35.100: D/AppListFragment(7649): onActivityCreated

11-29 14:26:35.120: D/AppListFragment(7649): onStart

11-29 14:26:35.120: D/AppListFragment(7649): onResume

屏幕灭掉:

11-29 14:27:35.185: D/AppListFragment(7649): onPause

11-29 14:27:35.205: D/AppListFragment(7649): onSaveInstanceState

11-29 14:27:35.205: D/AppListFragment(7649): onStop

屏幕解锁

11-29 14:33:13.240: D/AppListFragment(7649): onStart

11-29 14:33:13.275: D/AppListFragment(7649): onResume

切换到其他Fragment:

11-29 14:33:33.655: D/AppListFragment(7649): onPause

11-29 14:33:33.655: D/AppListFragment(7649): onStop

11-29 14:33:33.660: D/AppListFragment(7649): onDestroyView

切换回本身的Fragment:

11-29 14:33:55.820: D/AppListFragment(7649): onCreateView

11-29 14:33:55.825: D/AppListFragment(7649): onActivityCreated

11-29 14:33:55.825: D/AppListFragment(7649): onStart

11-29 14:33:55.825: D/AppListFragment(7649): onResume

回到桌面

11-29 14:34:26.590: D/AppListFragment(7649): onPause

11-29 14:34:26.880: D/AppListFragment(7649): onSaveInstanceState

11-29 14:34:26.880: D/AppListFragment(7649): onStop

回到应用

11-29 14:36:51.940: D/AppListFragment(7649): onStart

11-29 14:36:51.940: D/AppListFragment(7649): onResume

退出应用

11-29 14:37:03.020: D/AppListFragment(7649): onPause

11-29 14:37:03.155: D/AppListFragment(7649): onStop

11-29 14:37:03.155: D/AppListFragment(7649): onDestroyView

11-29 14:37:03.165: D/AppListFragment(7649): onDestroy

11-29 14:37:03.165: D/AppListFragment(7649): onDetach

onAttach()

作用:fragment已经关联到activity,
这个是 回调函数
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.i("onAttach_Fragment");
}
这个时候 activity已经传进来了
获得activity的传递的值
就可以进行 与activity的通信里

当然也可以使用getActivity(),前提是这个fragment已经和宿主的activity关联,并且没有脱离
他只调用一次。


onCreate()

系统创建fragment的时候回调他,在他里面实例化一些变量

这些个变量主要是:当你 暂停 停止的时候 你想保持的数据

如果我们要为fragment启动一个后台线程,可以考虑将代码放于此处。

参数是:Bundle savedInstance, 用于保存 Fragment 参数, Fragement 也可以 重写 onSaveInstanceState(BundleoutState) 方法, 保存Fragement状态;

可以用于 文件保护

他只调用一次。

onCreateView()
第一次使用的时候 fragment会在这上面画一个layout出来,
为了可以画控件 要返回一个 布局的view,也可以返回null

当系统用到fragment的时候 fragment就要返回他的view,越快越好,所以尽量在这里不要做耗时操作,比如从数据库加载大量数据显示listview,当然线程还是可以的。

给当前的fragment绘制ui布局,可以使用线程更新UI
说白了就是加载fragment的布局的。
这里一般都先判断是否为null

if(text==null){
Bundle args=getArguments();
text=args.getString("text");
}
if (view == null) {
view = inflater.inflate(R.layout.hello, null);
}


这样进行各判断省得每次都要加载,减少资源消耗

onActivityCreated()
当Activity中的onCreate方法执行完后调用。

注意了:
从这句官方的话可以看出:当执行onActivityCreated()的时候 activity的onCreate才刚完成。所以在onActivityCreated()调用之前 activity的onCreate可能还没有完成,所以不能再onCreateView()中进行 与activity有交互的UI操作,UI交互操作可以砸onActivityCreated()里面进行。
所以呢:这个方法主要是初始化那些你需要你的父Activity或者Fragment的UI已经被完整初始化才能初始化的元素。
如果在onCreateView里面初始化空间 会慢很多,比如listview等


onStart()
和activity一致 启动, Fragement 启动时回调, 此时Fragement可见;


onResume()
和activity一致  在activity中运行是可见的
激活, Fragement 进入前台, 可获取焦点时激活;


onPause()
和activity一致  其他的activity获得焦点,这个仍然可见
第一次调用的时候,指的是 用户 离开这个fragment(并不是被销毁)
通常用于 用户的提交(可能用户离开后不会回来了)


onStop()
和activity一致
fragment不可见的, 可能情况:activity被stopped了 OR  fragment被移除但被加入到回退栈中
一个stopped的fragment仍然是活着的如果长时间不用也会被移除


onDestroyView()
Fragment中的布局被移除时调用。
表示fragemnt销毁相关联的UI布局
清除所有跟视图相关的资源

以前以为这里没什么用处其实 大有文章可做,
相信大家都用过ViewPager+Fragment,由于ViewPager的缓存机制,每次都会加载3页。
例如:有四个 fragment 当滑动到第四页的时候 第一页执行onDestroyView(),但没有执行onDestroy。他依然和activity关联。当在滑动到第一页的时候又执行了 onCreateView()。 生命周期可以自己试一下。
那么问题来了。会出现重复加载view的局面,所以这么做(下面是先人的代码)

@Override
public void onDestroyView() {
Log.i("onDestroyView_Fragment");
if(view!=null){
((ViewGroup)view.getParent()).removeView(view);
}
super.onDestroyView();
}


onDestroy()
销毁fragment对象
跟activity类似了。


onDetach()
Fragment和Activity解除关联的时候调用。
脱离activity


可见fragment的销毁还是很优雅地,一个一个的来。

Fragment的生命周期

  你可以把fragment看作是activity的模块化组件,它拥有自己的生命周期

  

  Fragment是activity的界面中的一部分或一种行为。你可以把多个Fragment们组合到一个activity中来创建一个多面界面并且你可以在多个activity中重用一个Fragment。你可以把Fragment认为模块化的一段activity,它具有自己的生命周期,接收它自己的事件,并可以在activity运行时被添加或删除。

  Fragment不能独立存在,它必须嵌入到activity中,而且Fragment的生命周期直接受所在的activity的影响。例如:当activity暂停时,它拥有的所有的Fragment们都暂停了,当activity销毁时,它拥有的所有Fragment们都被销毁。然而,当activity运行时(在onResume()之后,onPause()之前),你可以单独地操作每个Fragment,比如添加或删除它们。当你在执行上述针对Fragment的事务时,你可以将事务添加到一个栈中,这个栈被activity管理,栈中的每一条都是一个Fragment的一次事务。有了这个栈,就可以反向执行Fragment的事务,这样就可以在Fragment级支持“返回”键(向后导航)。

  

  显示Fragment时(跟用户交互)要调用的核心的生命周期方法如下:

  1. 把Fragment对象跟Activity关联时,调用onAttach(Activity)方法;

  2. Fragment对象的初始创建时,调用onCreate(Bundle)方法;

  3. onCreateView(LayoutInflater, ViewGroup, Bundle)方法用于创建和返回跟Fragment关联的View对象;

  4. onActivityCreate(Bundle)方法会告诉Fragment对象,它所依附的Activity对象已经完成了Activity.onCreate()方法的执行;

  5. onStart()方法会让Fragment对象显示给用户(在包含该Fragment对象的Activity被启动后);

  6. onResume()会让Fragment对象跟用户交互(在包含该Fragment对象的Activity被启恢复后)。

  

  Fragment对象不再使用时,要反向回调的方法:

  1. 因为Fragment对象所依附的Activity对象被挂起,或者在Activity中正在执行一个修改Fragment对象的操作,而导致Fragment对象不再跟用户交互时,系统会调用Fragment对象的onPause()方法;

  2. 因为Fragment对象所依附的Activity对象被终止,或者再Activity中正在执行一个修改Fragment对象的操作,而导致Fragment对象不再显示给用户时,系统会调用Fragment对象的onStop()方法。

  3. onDestroyView()方法用于清除跟Fragment中的View对象关联的资源;

  4. Fragment对象的状态被最终清理完成之后,要调用onDestroy()方法;

  5. 在Fragment对象不再跟它依附的Activity关联的时候,onDetach()方法会立即被调用

1.4 Frament 管理
要管理 fragment,需使用 FragmentManager,要获取它,需在 activity 中调用方法 getFragmentManager()。 可以用 FragmentManager 来做以上事情:

使用方法 findFragmentById()或 findFragmentByTag(),获取 activity 中已存在的 fragment

使用方法 popBackStack()从 activity 的后退栈中弹出 fragment(这可以模拟后退键引发的动作)
用方法 addOnBackStackChangedListerner()注册一个侦听器以监视后退栈的变化

还可以使用 FragmentManager 打开一个 FragmentTransaction 来执行 fragment 的事务,比如添加或删除 fragment。
在 activity 中使用 fragment 的一个伟大的好处是能跟据用户的输入对 fragment 进行添加、删除、替换以及执行 其它动作的能力。提交的一组 fragment 的变化叫做一个事务。事务通过 FragmentTransaction 来执行。还可以把每个 事务保存在 activity 的后退栈中,这样就可以让用户在 fragment 变化之间导航(跟在 activity 之间导航一样)。
可以通过 FragmentManager 来取得 FragmentTransaction 的实例,如下:

FragmentManagerfragmentManager = getFragmentManager();

FragmentTransactionfragmentTransaction =fragmentManager.beginTransaction(); 一个事务是在同一时刻执行的一组动作(很像数据库中的事务)。可以用 add(),remove(),replace()等方法构成事
务,最后使用 commit()方法提交事务。在调用 commint()之前,可以用 addToBackStack()把事务添加到一个后退栈中, 这个后退栈属于所在的 activity。有了它,就可以在用户按下返回键时,返回到 fragment 执行事务之前的状态。如 下例:演示了如何用一个 fragment 代替另一个 fragment,同时在后退栈中保存被代替的 fragment 的状态。
//Create new fragment and transaction

Fragment newFragment = newExampleFragment();

FragmentTransaction transaction=getFragmentManager().beginTransaction();
//Replace whatever is in the fragment_container view with thisfragment, //and add the transaction to the backstack

t ransact ion.rep lace(R.id.fra gm ent _cont ainer,new Fra gment );

transaction.addToBackStack(null) ;

//Commit the transaction transaction.commit();
解释:newFragment 代替了控件 IDR.id.fragment_container 所指向的 ViewGroup 中所含的任何 fragment。然后调 用 addToBackStack(),此时被代替的 fragment 就被放入后退栈中,于是当用户按下返回键时,事务发生回溯,原先 的 fragment 又回来了。
如果向事务添加了多个动作,比如多次调用了 add(),remove()等之后又调用了 addToBackStack()方法,那么所有 的在 commit()之前调用的方法都被作为一个事务。当用户按返回键时,所有的动作都被反向执行(事务回溯)。
事务中动作的执行顺序可随意,但要注意以下两点:

必须最后调用 commit()

如果添加了多个 fragment,那么它们的显示顺序跟添加顺序一至(后显示的覆盖前面的) 如果在执行的事务中有删除 fragment 的动作,而且没有调用 addToBackStack(),那么当事务提交时,那些被删
除的 fragment 就被销毁了。反之,那些 fragment 就不会被销毁,而是处于停止状态。当用户返回时,它们会被恢复。 但是,调用 commit()后,事务并不会马上执行。它会在 activity 的 UI 线程(其实就是主线程)中等待直到线程 能执行的时候才执行(废话)。如果必要,可以在 UI 线程中调用 executePendingTransactions()方法来立即执行事务。
但一般不需这样做,除非有其它线程在等待事务的执行。

注意:只能在 activity 处于可保存状态的状态时,比如 running 中,onPause()方法和 onStop()方法中提交事务, 否则会引发异常。这是因为 fragment 的状态会丢失。如果要在可能丢失状态的情况下提交事务,请使用 commitAllowingStateLoss()。
1.5 Fragment 与 Activity 通讯
尽管 fragment 的实现是独立于 activity 的,可以被用于多个 activity,但是每个 activity 所包含的是同一个 fragment 的不同的实例。Fragment 可以调用 getActivity()方法很容易的得到它所在的 activity 的对象,然后就可以查找 activity 中的控件们(findViewById())。例如:

ViewlistView =getActivity().findViewById(R.id.list);同样的,activity 也可以通过 FragmentManager 的方 法查找它所包含的 frament 们。
例如:
Examp leFra gment

fragment =(ExampleFragment)getFragmentManager().findFragmentById(R.id.example_fragment )
有时,可能需要 fragment 与 activity 共享事件。一个好办法是在 fragment 中定义一个回调接口,然后在 activity 中实现之。例如,还是那个新闻程序的例子,它有一个 activity,activity 中含有两个 fragment。fragmentA 显示新闻标题,fragmentB 显示标题对应的内容。fragmentA 必须在用户选择了某个标题时告诉 activity,然后
activity 再告诉 fragmentB,fragmentB 就显示出对应的内容。
如下例,OnArticleSelectedListener 接口在 fragmentA 中定义:
public static class FragmentA extends ListFragment{ //Container Activity must implement this interface
public interface OnArticleSelectedListener{

public void onArticleSelected(Uri articleUri);
}
然后 activity 实现接口 OnArticleSelectedListener,在方法 onArticleSelected()中通知 fragmentB。当 fragment 添加到 activity 中时,会调用 fragment 的方法 onAttach(),这个方法中适合检查 activity 是否实现了

OnArticleSelectedListener 接口,检查方法就是对传入的 activity 的实例进行类型转换,如下所示:
public static class FragmentA extends ListFragment{ OnArticleSelectedListenermListener;

...

@Override
public void onAttach(Activity activity){ super.onAttach(activity);

try{
mListener =(OnArticleSelectedListener)activity; }catch(ClassCastException e){
throw new ClassCastException(activity.toString()+"must implement OnArticleSelectedListener"); }
}
如果 activity 没有实现那个接口,fragment 抛出 ClassCastException 异常。如果成功了,mListener 成员变 量保存 OnArticleSelectedListener 的实例。于是 fragmentA 就可以调用 mListener 的方法来与 activity 共享事 件。例如,如果 fragmentA 是一个 ListFragment,每次选中列表的一项时,就会调用
fragmentA 的 onListItemClick() 方法,在这个方法中调用 onArticleSelected()来与 activity 共享事件,如下:

public static class FragmentA extends ListFragment{
OnArticleSelectedListenermListener;

...

@Override

public void onListItemClick(ListViewl,Viewv,intposition,long id){
//Append the clicked item's row ID with the content provider Uri

Uri noteUri =ContentUris.withAppendedId(ArticleColumns.CONTENT_URI,id); //Send the event and Uri to the host activity mListener.onArticleSelected(noteUri);
}

onListItemClick()传入的参数 id 是列表的被选中的行 ID,另一个 fragment 用这个 ID 来从程序的
ContentProvider 中取得标题的内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: