activity的生命周期

来源:互联网 发布:运动控制编程 编辑:程序博客网 时间:2024/06/05 19:22

1.单个activity的生命周期图
activity是android的四大组件之一,负责界面内容,给用户提供交互接口。映射到mvc模型中,activity相当于view。图1.1描述了activity的基本的生命周期。

如图所示,activity在存在期间,会回调onCreate,onStart,onResume,onPause, onStop,onRestart,onSaveInstanceState, onDestory这八个方法。
onCreate方法是activity第一次创建的时候回调,一般在这里要做的事情包括创建视图(setContentView())、向视图填充必要的数据,如果咱们需要请求网络数据,通常在此处开启网络请求线程,这样可以将耗时的异步线程与主线程的UI绘制并行执行。此时activity还不可见。
onStart方法是activity从不可见变成可见的时候执行的方法。此时activity对于用户来说是可见的,包括有一个activity在他上面,但没有将它完全覆盖的情况,此时用户可以看到该activity,但是不能与它交互。
onResume方法是activity处于可见状态,并且获取了焦点,用户可以与该activity进行交互。
onPause方法是activity处于可见状态,但是已经失去了操作焦点,用户已经不可以操作该activity的内部组件了。此时它依然与窗口管理器保持连接。当activity再次变的可以点击的时候,那activity会回调onResume方法,进入可见可操作的状态。
onSaveInstanceState方法是android系统提供给开发者在activity会发生非正常kill风险之前调用,以便保存activity的状态,这样就可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle)中恢复,onCreate(Bundle)与onRestoreInstanceState(Bundle)中传入的Bundle参数就是activity上一次调用onSaveInstanceState保存的Bundle数据。
onSaveInstanceState的调用时机是由系统决定的,对于开发者来说,在开发过程中分析系统是否会调用onSaveInstanceState回调方法的时候需要遵循一个重要原则,即当系统“未经开发者许可”时销毁了当前的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。以下是几个常见的调用onSaveInstanceState方法的场景。
1、当用户按下HOME键时。
2、长按HOME键,选择运行其他的程序时。
3、按下电源按键(关闭屏幕显示)时。
4、从activity A中启动一个新的activity时。
5、屏幕方向切换时,例如从竖屏切换到横屏时。
在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行。
onStop方法是activity完全不可见的时候回调的,此时系统任务栈中还存在该activity的引用。
onDestory方法回调之后系统会销毁这个Activity实例在内存中占据的空间。在Activity的生命周期中,onDestory()方法是他生命的最后一步,资源空间等就被回收了。当重新进入此Activity的时候,必须重新创建,执行onCreate()方法。

2.startActivity启动流程
本文为了更好的说明activity的启动流程,假想以下的activity都是standard的启动模式。
场景: activity A 中点击了某个按钮之后,启动 activity B
图示:

生命周期流程:

如图所示,A首先会调用onPause回调方法,之后会调用B的onCreate,onStart,onResume回调方法,最后调用A的onStop方法。
A在onPause之后会发起启动B的流程,并且此时A已经不可以操作了。因此
在activity的onStop生命周期里面,我们最好停止掉activity  A中消耗系统资源的操作比如停止一切动画,清除广播接受者,释放传感处理器等。另外,在onPause中要避免发生cpu敏感的行为,比如写入数据库,这会影响切换到下一个activity的显示效果总之,在onPause中的操作都应该是非常简单的,低性能消耗的,确保在onStop()被调用时,用户向其他界面的切换是迅速流畅的。当activity处于pause状态的时候,activity的实例继续常驻在内存中,当onresume发生的时候被重新调用。 你不需要重新初始化在onResume之前的任何阶段创建的控件.

场景:activity A在自己的onCreate生命周期里面启动了activity B,并且在此之前通过handler调用sendEmptyMessage方法向循环队列里面放一条message。
代码:
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        。。。。。。
        Handler temp = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d("test122q", "a message form A in onCreate Method");
            }
        };
     startActivity(new Intent(A.this, B.class));

        temp.sendEmptyMessage(1);

  }


生命周期流程:

如图所示,如果在activity A启动时,向主循环队列中发送一个message,并且启动了另外一个activity B.那么系统会在完成启动activity A的流程之后,才会处理在onCreate里面发送的message,之后才会启动activity B。这样的处理结果其实跟Android系统启动activity的方式有关。activity在调用startActivity启动新的activity的时候,会通过Binder进程通信机制与AMS进行同行,让AMS决定怎么启动ativity,通常需要考虑activity的启动模式,当前的系统任务栈,内存中的activity对象等因数,总之这是一个耗时的操作,并且处理的操作是运行在AMS的进程中,当AMS处理完成之后,会将启动activity的messgae放到合适的循环队列中,这样应用的主循环队列就能获取启动新的activity的message,以达到启动新的activity的目的。下图显示了activity启动新的activity的消息处理过程。
由于AMS的处理是需要花费时间的,因此在本例中,启动activiy B输出的日志会在A中的handler输出的日志之后,但是如果将temp.sendEmptyMessage(1);发送消息的方法延长合适的时间发送,那么A中的handler输出的日志会在启动activiy B输出的日志之后。

测试代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        。。。。。。
        Handler temp = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d("test122q", "a message form A in onCreate Method");
            }
        };
     startActivity(new Intent(A.this, B.class));

        temp.sendEmptyMessageDelayed(1, 5000);

  }

输出日志:
通过输出日志,我们可以看出,将A的onCreate中发送message的时间延时5000ms之后,该message的日志会在最后输出,因为这段时间足够AMS处理activity B的启动工作了。


注意点:
1。activity的onPause方法回调的时候,用户已经不能与该activity进行交互,此时最好关闭activity中消耗CPU与系统资源的操作,特别是动画。
2。activity的onSaveInstanceState是系统在有可能发生将activity在未经APP允许的情况下KILL掉的时候回调,以便在activity因为内存不足等原因被系统杀死后重新恢复时,调用onCreate的时候能够传入之前保存的bundle参数,已达到恢复线程的功能。
3。activity启动新的activity的时候,会通过bind机制通知AMS进行调度处理,AMS处理完成之后,会通过消息队列通知应用启动相应的activity。

1 0