Android系列之Fragment(二)----Fragment的生命周期和返回栈

?【声明】

欢迎转载,但请保留文章原始出处→_→

生命壹号:http://www.cnblogs.com/smyhvae/

文章来源:http://www.cnblogs.com/smyhvae/p/3983234.html

联系方式:[email protected]

【正文】

上一章节中(Android系列之Fragment(一)----Fragment加载到Activity当中),我们对Fragment的生命周期进行了简单介绍,这一章节将对生命周期和返回栈进行详细介绍。

一、Fragment的生命周期初探:

因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的。

如果Activity是暂停状态,其中所有的Fragment都是暂停状态;如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动;如果Activity被销毁,那么它其中的所有Fragment都会被销毁。

但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除Fragment。

当这样进行fragment transaction(转换)的时候,可以把fragment放入Activity的back stack中,这样用户就可以进行返回操作。

使用Fragment时,需要继承Fragment或者Fragment的子类(DialogFragment, ListFragment, PreferenceFragment, WebViewFragment),所以Fragment的代码看起来和Activity的类似。

每当创建一个Fragment时,首先添加以下三个回调方法:

  • onCreate():系统在创建Fragment的时候调用这个方法,这里应该初始化相关的组件,一些即便是被暂停或者被停止时依然需要保留的东西。
  • onCreateView():当第一次绘制Fragment的UI时系统调用这个方法,该方法将返回一个View,如果Fragment不提供UI也可以返回null。注意,如果继承自ListFragment,onCreateView()默认的实现会返回一个ListView,所以不用自己实现。
  • onPause():当用户离开Fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。

将Fragment加载到Activity当中有两种方式:

  • 方式一:添加Fragment到Activity的布局文件当中
  • 方式二:在Activity的代码中动态添加Fragment(荐)

第一种方式虽然简单但灵活性不够。添加Fragment到Activity的布局文件当中,就等同于将Fragment及其视图与activity的视图绑定在一起,且在activity的生命周期过程中,无法切换fragment视图。

第二种方式比较复杂,但也是唯一一种可以在运行时控制fragment的方式(加载、移除、替换)。

二、Fragment的生命周期详解:

先来看一下官方文档的图片吧:

我们再把Activity的生命周期和Fragment的生命周期对比一下,就清楚很多了:

我们还是在实例中来看一下Fragment的生命周期吧。

【实例】在MainActivity中加载一个Fragment:(完整版代码如下)

我们所创建的Fragment的布局文件fragment01.xml的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <RatingBar
        android:id="@+id/ratingBar1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>

MyFragment.java代码如下:(注意生命周期中每个方法的作用)

  1 package com.example.m01_fragmentlifecycle;
  2
  3 import android.app.Activity;
  4 import android.app.Fragment;
  5 import android.os.Bundle;
  6 import android.util.Log;
  7 import android.view.LayoutInflater;
  8 import android.view.View;
  9 import android.view.ViewGroup;
 10
 11 public class MyFragment extends Fragment {
 12     private final String TAG = "MyFragment";
 13
 14     //获得activity的传递的值
 15     @Override
 16     public void onAttach(Activity activity) {
 17         // TODO Auto-generated method stub
 18         super.onAttach(activity);
 19         Log.i(TAG, "--MyFragment->>onAttach");
 20     }
 21
 22     //实例化成员变量
 23     @Override
 24     public void onCreate(Bundle savedInstanceState) {
 25         // TODO Auto-generated method stub
 26         super.onCreate(savedInstanceState);
 27         Log.i(TAG, "--MyFragment->>onCreate");
 28     }
 29
 30     //给当前的fragment绘制UI布局,可以使用线程更新UI
 31     @Override
 32     public View onCreateView(LayoutInflater inflater, ViewGroup container,
 33             Bundle savedInstanceState) {
 34         Log.i(TAG, "--MyFragment->>onCreateView");
 35         View view = inflater.inflate(R.layout.fragment01, null);
 36         // TODO Auto-generated method stub
 37         return view;
 38     }
 39
 40     //表示activity执行oncreate方法完成了的时候会调用此方法
 41     @Override
 42     public void onActivityCreated(Bundle savedInstanceState) {
 43         // TODO Auto-generated method stub
 44         super.onActivityCreated(savedInstanceState);
 45         Log.i(TAG, "--MyFragment->>onActivityCreated");
 46     }
 47
 48     //和activity一致
 49     @Override
 50     public void onStart() {
 51         // TODO Auto-generated method stub
 52         super.onStart();
 53         Log.i(TAG, "--MyFragment->>onStart");
 54     }
 55
 56     //和activity一致
 57     @Override
 58     public void onResume() {
 59         // TODO Auto-generated method stub
 60         super.onResume();
 61         Log.i(TAG, "--MyFragment->>onResume");
 62     }
 63
 64     //和activity一致
 65     @Override
 66     public void onPause() {
 67         // TODO Auto-generated method stub
 68         super.onPause();
 69         Log.i(TAG, "--MyFragment->>onPause");
 70     }
 71
 72     //和activity一致
 73     @Override
 74     public void onStop() {
 75         // TODO Auto-generated method stub
 76         super.onStop();
 77         Log.i(TAG, "--MyFragment->>onStop");
 78     }
 79
 80     //表示fragment销毁相关联的UI布局
 81     @Override
 82     public void onDestroyView() {
 83         // TODO Auto-generated method stub
 84         super.onDestroyView();
 85         Log.i(TAG, "--MyFragment->>onDestroyView");
 86     }
 87
 88     //销毁fragment对象
 89     @Override
 90     public void onDestroy() {
 91         // TODO Auto-generated method stub
 92         super.onDestroy();
 93         Log.i(TAG, "--MyFragment->>onDestroy");
 94     }
 95
 96     //脱离activity
 97     @Override
 98     public void onDetach() {
 99         // TODO Auto-generated method stub
100         super.onDetach();
101         Log.i(TAG, "--MyFragment->>onDetach");
102     }
103 }

activity_main.xml的代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/line"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    </LinearLayout>

</LinearLayout>

MainActivity.java的代码如下:

 1 package com.example.m01_fragmentlifecycle;
 2
 3 import android.os.Bundle;
 4 import android.app.Activity;
 5 import android.app.FragmentManager;
 6 import android.app.FragmentTransaction;
 7 import android.util.Log;
 8 import android.view.Menu;
 9
10 public class MainActivity extends Activity {
11     private final String TAG = "MainActivity";
12     private FragmentManager manager;
13     private FragmentTransaction transaction;
14
15     @Override
16     protected void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.activity_main);
19         manager = getFragmentManager();
20         transaction = manager.beginTransaction();
21         MyFragment fragment = new MyFragment();
22         transaction.add(R.id.line, fragment);
23         transaction.commit();
24         Log.i(TAG, "--MainActivity->>onCreate");
25     }
26
27     @Override
28     protected void onStart() {
29         // TODO Auto-generated method stub
30         super.onStart();
31         Log.i(TAG, "--MainActivity->>onStart");
32     }
33
34     @Override
35     protected void onResume() {
36         // TODO Auto-generated method stub
37         super.onResume();
38         Log.i(TAG, "--MainActivity->>onResume");
39     }
40
41     @Override
42     protected void onPause() {
43         // TODO Auto-generated method stub
44         super.onPause();
45         Log.i(TAG, "--MainActivity->>onPause");
46     }
47
48     @Override
49     protected void onStop() {
50         // TODO Auto-generated method stub
51         super.onStop();
52         Log.i(TAG, "--MainActivity->>onStop");
53     }
54
55     @Override
56     protected void onRestart() {
57         // TODO Auto-generated method stub
58         super.onRestart();
59         Log.i(TAG, "--MainActivity->>onRestart");
60     }
61     @Override
62     protected void onDestroy() {
63         // TODO Auto-generated method stub
64         super.onDestroy();
65         Log.i(TAG, "--MainActivity->>onDestroy");
66     }
67
68     @Override
69     public boolean onCreateOptionsMenu(Menu menu) {
70         // Inflate the menu; this adds items to the action bar if it is present.
71         getMenuInflater().inflate(R.menu.main, menu);
72         return true;
73     }
74 }

可以看到,上面的代码在每个生命周期的方法里都打印了日志,然后我们来运行一下程序,可以看到打印日志如下:

初次加载:(分成两部分来看)

点击一下home键(或接入电话),打印日志如下:

重新进入进入程序(或电话结束),打印日志如下:

点击back键退出程序,打印日志如下:

通过上面的日志,我们能够看出,Fragment和Activity的生命周期太相似了。只是有几个Activity中没有的新方法,需要重点介绍一下:

  • onAttach方法:Fragment和Activity建立关联的时候调用(获得activity的传递的值)
  • onCreateView方法:为Fragment创建视图(加载布局)时调用(给当前的fragment绘制UI布局,可以使用线程更新UI)
  • onActivityCreated方法:当Activity中的onCreate方法执行完后调用(表示activity执行oncreate方法完成了的时候会调用此方法)
  • onDestroyView方法:Fragment中的布局被移除时调用(表示fragment销毁相关联的UI布局)
  • onDetach方法:Fragment和Activity解除关联的时候调用(脱离activity)

三、Fragment返回栈的管理:

将Fragment添加到返回栈中:

假设现在我们有两个Fragment:Fragment01和Fragment02,我们现在从Fragment01的界面跳到Fragment02,然后按Back键,发现程序是直接退出了,而不是返回到Fragment01。如果现在想实现以下功能:从Fragment01的界面跳到Fragment02,然后按Back键,会返回到Fragment01。这个功能该怎么实现呢?这其实就利用到了返回栈的知识。

其实很简单,FragmentTransaction中提供了一个addToBackStack()方法,可以将一个事务添加到返回栈中。

我们先回顾一下之前动态加载Fragment的代码,然后在此基础之上,增加一行代码就可以将Fragment添加到返回栈中:(即第07行代码)

1                 //步骤一:添加一个FragmentTransaction的实例
2                 FragmentManager fragmentManager =getFragmentManager();
3                 FragmentTransaction transaction = fragmentManager.beginTransaction();
4                 //步骤二:用add()方法加上Fragment的对象
5                 RightFragment rightFragment = new RightFragment();
6                 transaction.add(R.id.right, rightFragment);
7                 transaction.addToBackStack(null);
8                 //步骤三:调用commit()方法使得FragmentTransaction实例的改变生效
9                 transaction.commit(); 

第07行代码:我们在事务提交之前调用了FragmentTransaction的addToBackStack()方法,它可以接受一个名字用于描述返回栈的状态,,一般传入null即可。

【实例】现在通过代码来实现以下界面(下面的图片为程序运行时加载的首页),并且把每一个Fragment都加入到返回栈当中去,然后观察其生命周期的变化。完整代码如下:

首先新建工程文件m01_Fragment04,然后开始我们的代码之旅:

我们先把右侧的四个Fragment建起来吧:

Fragment01.java主要部分的代码如下:

 1 package com.example.m01_fragment04;
 2
 3 import android.app.Fragment;
 4 import android.os.Bundle;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8
 9 public class Fragment01 extends Fragment {
10
11     @Override
12     public void onCreate(Bundle savedInstanceState) {
13         super.onCreate(savedInstanceState);
14     }
15
16     @Override
17     public View onCreateView(LayoutInflater inflater, ViewGroup container,
18             Bundle savedInstanceState) {
19         View view = inflater.inflate(R.layout.f1, null);
20         return view;
21     }
22     @Override
23     public void onPause() {
24         super.onPause();
25     }
26 }

为避免啰嗦,这里就不把Fragment01生命周期中的其他函数罗列出来了,我们只要知道在实际代码中这些函数都是加了的。

Fragment01的布局文件f1.xml的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加载图片" />
</LinearLayout>

然后依次新建出Fragment02、Fragment03、Fragment04的java代码和布局文件。

MainActivity的布局文件activity_main.xml代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/left"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="#CCCCCC"
        android:orientation="vertical" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="加载图片" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="海报管理" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="照片管理" />

        <Button
            android:id="@+id/button4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="新闻管理" />        

    </LinearLayout>

    <LinearLayout
        android:id="@+id/right"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >
    </LinearLayout>

</LinearLayout>

其中,第一个LinearLayout表示左侧的按钮,第二个LinearLayout留给右边的Fragment。

MainActivity.java的代码如下:

 1 package com.example.m01_fragment04;
 2
 3 import android.os.Bundle;
 4 import android.app.Activity;
 5 import android.app.FragmentManager;
 6 import android.app.FragmentTransaction;
 7 import android.view.Menu;
 8 import android.view.View;
 9 import android.view.View.OnClickListener;
10 import android.widget.Button;
11
12 public class MainActivity extends Activity  implements OnClickListener{
13
14     private FragmentManager manager;
15     private FragmentTransaction transaction;
16     private Button button1,button2,button3,button4;
17
18     @Override
19     protected void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main);
22
23     manager = getFragmentManager();
24         button1 = (Button)this.findViewById(R.id.button1);
25         button1.setOnClickListener(this);
26         button2 = (Button)this.findViewById(R.id.button2);
27         button2.setOnClickListener(this);
28         button3 = (Button)this.findViewById(R.id.button3);
29         button3.setOnClickListener(this);
30         button4 = (Button)this.findViewById(R.id.button4);
31         button4.setOnClickListener(this);
32
33     }
34
35     @Override
36     public boolean onCreateOptionsMenu(Menu menu) {
37         // Inflate the menu; this adds items to the action bar if it is present.
38         getMenuInflater().inflate(R.menu.main, menu);
39         return true;
40     }
41
42     //通过点击不同的按钮,跳转到不同的Fragment
43     @Override
44     public void onClick(View v) {
45         // TODO Auto-generated method stub
46         transaction = manager.beginTransaction();
47         switch (v.getId()) {
48         case R.id.button1:
49             Fragment01 fragment01 = new Fragment01();
50             transaction.replace(R.id.right, fragment01, "fragment01");
51             transaction.addToBackStack("fragment01");// 添加到Activity管理的回退栈中。
52             break;
53
54         case R.id.button2:
55             Fragment02 fragment02 = new Fragment02();
56             transaction.replace(R.id.right, fragment02, "fragment02");
57             transaction.addToBackStack("fragment02");// 添加到Activity管理的回退栈中。
58             break;
59
60         case R.id.button3:
61             Fragment03 fragment03 = new Fragment03();
62             transaction.replace(R.id.right, fragment03, "fragment03");
63             transaction.addToBackStack("fragment03");// 添加到Activity管理的回退栈中。
64             break;
65
66         case R.id.button4:
67             Fragment04 fragment04 = new Fragment04();
68             transaction.replace(R.id.right, fragment04, "fragment04");
69             transaction.addToBackStack("fragment04");// 添加到Activity管理的回退栈中。
70             break;
71         }
72         transaction.commit();   
73     }
74
75 }

上当代码中,通过点击不同的按钮,就能跳到对应的Fragment,而这四个Fragment都已经加入到了返回栈当中。运行程序之后,也是这样的。

注意第46行和第72行,transaction = manager.beginTransaction()意味着开始,transaction.commit()意味着结束。

我们就其中的fragment01和fragment02来讨论一下他们的生命周期的变化:

运行程序后,界面如下,没有任何fragment被加载:

点击左侧第一个按钮,加载fragment01:

点击左侧第二个按钮,加载fragment02(此时fragment01被替换,并被压到了栈当中):

注:如果fragment01在替换的时候没有被压到栈中,那就会被销毁,在执行完onDestroyView()方法后,会继续执行onDestroy()和onDetach()方法。

按Back键,fragment01重新返回到屏幕:(fragment02被销毁)

再按Back键,fragment01被销毁:

注:Fragment的返回栈由Activity管理;而Activity的返回栈由系统管理。

【工程文件】

链接:http://pan.baidu.com/s/1i3DrYmx

密码:uh46

时间: 2024-10-26 23:59:04

Android系列之Fragment(二)----Fragment的生命周期和返回栈的相关文章

Android系列之Fragment(二)Fragment的生命周期和返回栈

Android系列之Fragment(二)Fragment的生命周期和返回栈 - Android - 次元立方网 - 电脑知识与技术互动交流平台 [正文] 上一章节中(Android系列之Fragment(一)----Fragment加载到Activity当中),我们对Fragment的生命周期进行了简单介绍,这一章节将对生命周期和返回栈进行详细介绍. 一.Fragment的生命周期初探: 因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activ

Android_Fragment的生命周期与返回栈BackStack

一.Fragment的生命周期初探 因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的. 如果Activity是暂停状态,其中所有的Fragment都是暂停状态:如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动:如果Activity被销毁,那么它其中的所有Fragment都会被销毁. 但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除F

android开发学习笔记(二)-activity的生命周期

一:activity的生命周期: 二:created->resumed 当一个应用程序的启动图标被用户点击后,应用程序开始从Activity的onCreate()方法开始执行.(当有多个activity文件时,执行Manifest文件中指定的主activity文件). 当执行完onCreate()方法后,迅速调用onStart(),onResume()方法,用户就可以进行相关的操作. 在onCreate()方法中尽量少执行操作,防止程序运行很久都进入不了界面. 三:Resumed->Pause

Android基础笔记(八)- Activity生命周期与任务栈

Activity的生命周期 横竖屏切换问题 任务栈的概念 Activity的4种启动模式 Activity的生命周期 Activity整个的生命周期如下所示,这张图是从Android API上扒下来了,我觉得API上关于生命周期已经讲解的很详细了,我也就不啰嗦了,就简要的说下自己的一些总结: 做工作中,你可能感兴趣的三个关键环 ① 完整生命周期 ② 可见生命周期 ③ 可交互生命周期 如图所示,图中的周期都是大的包括小的: 在实际工作中的使用 ①onResume可见, 可交互..把动态刷新的操作启

Android学习路线(十二)Activity生命周期——启动一个Activity

先占个位置,过会儿来翻译,:p Unlike other programming paradigms in which apps are launched with a main()method, the Android system initiates code in an Activity instance by invoking specific callback methods that correspond to specific stages of its lifecycle. Th

17.(转) Android之四大基本组件介绍与生命周期

Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器. 一:了解四大基本组件 Activity : 应用程序中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应. Activity之间通过Intent进行通信.在Intent 的描述结构中,有两个最重要的部分:动作和动作对应的数据. 典型的动作类型有:M AIN(activity的门户).V

【Android笔记】(1)—— Activity生命周期与通信

一.Activity 1.Activity状态 活动中:如果Activity在屏幕前,即是可视的,可接受用户的输入. 暂停状态:Activity失去焦点,但仍然可见. 停止状态:如果一个Activity被另一个Activity遮住了,它的状态时停止的. 2.Activity生命周期动作方法 onRestart() : Activity第一次被创建时调用,用于初始化一些数据,如View,此时处于停止状态. onStart(): Activity将要对用户可见时调用,调用后进入停止状态. onRes

Spark源码系列(四)图解作业生命周期

这一章我们探索了Spark作业的运行过程,但是没把整个过程描绘出来,好,跟着我走吧,let you know! 我们先回顾一下这个图,Driver Program是我们写的那个程序,它的核心是SparkContext,回想一下,从api的使用角度,RDD都必须通过它来获得. 下面讲一讲它所不为认知的一面,它和其它组件是如何交互的. Driver向Master注册Application过程 SparkContext实例化之后,在内部实例化两个很重要的类,DAGScheduler和TaskSched

iOS系列 基础篇 03 探究应用生命周期

iOS系列 基础篇 03 探究应用生命周期 目录: 1. 非运行状态 - 应用启动场景 2. 点击Home键 - 应用退出场景 3. 挂起重新运行场景 4. 内存清除 - 应用终止场景 5. 结尾 本篇主要探讨的是iOS应用中各种状态的跃迁过程,建议大家通过修改AppDelegate.swift,在每个过程中添加日志输出代码,从而观察其变化. 作为应用程序的委托对象,AppDelegate类在应用程序生命周期的不同阶段会回调不同的方法. 首先,咱们先来了解一下iOS应用的不同状态和他们之间的关系