Activity的生命周期和启动模式

Activity的生命周期

典型情况下的生命周期分析

  • onCreate()
    • 第一个生命周期方法,一般在这个方法做初始化工作,比如调用setContentView去加载界面布局资源,初始化Activity所需要的数据等。
  • onStart()
  • onRestart()
  • onResume()
  • onPause()
    • 可见,但不可交互的情况。一般在这个方法做一些动画暂停操作。同时,onPause()必须先执行完,新的Activity的onResume()才能执行。
  • onStop()
    • 可做一些稍重量级的回收工作
  • oDestory()
    • Activity生命周期里的最后一个回调方法,一般在这里做垃圾回收和资源释放工作。

问题1:
当前Activity为A,用户打开一个新的ActivityB,那么B的onResume()和A的onPause()哪个先执行?
答:Activity的启动过程比较复杂,涉及Instrumentation、ActivityThread和ActivityManagerService(简称:AMS)。简单来说,启动Activity的请求会有Instrumentation来处理,然后它通过Binder小AMS发送请求,AMS内部维护着一个ActivityStack并负责着栈内Activity的状态同步,AMS通过ActivityThread去同步Activity的状态从而完成生命周期的调用。
具体解析:P4-P6

异常情况下的生命周期分析

  • 资源相关的系统配置发送改变导致Activity被杀死被重新创建。
  • 资源内存不足导致低优先级的Activity被杀死。
    • 如果一个进程中没有四大组件在执行,那么这个进程将很快被系统杀死,所以后台操作适合放入Service中从而保证进程的优先级。
onSaveInstanceState()/onRestoreInstanceState()

Activity:
在Activity异常终止的时候,系统会调用onSaveInstanceState()来保存Activity的状态,这个方法的调用时机在onStop()之前,可能在onPause()之前,也可能在它之后。当Activity被重新创建的时候,系统或调用onRestoreInstanceState(),并把之前在onSaveInstanceState()所保存的Bundle对象作为参数同时传递给onRestoreInstanceState()和onCreate()方法。onRestoreInstanceState()会在onStart()之后调用。

View:
当Activity在异常情况下需要重新创建的时候,系统会默认为我们保存当前Activity的视图结构,并在重建的时候为我们恢复这些数据,比如文本框中输入的数据,ListView的滚动位置等,这些View相关的状态系统都默认为我们保存恢复,根据View的源码。和Activity一样,每个View都有onSaveInstanceState()/onRestoreInstanceState()。恢复流程:首先Acitivity被意外终止,Activity调用onSaveInstanceState()保存数据,然后Activity会委托Window保存数据,接着Window再委托它上面的顶级容器去保存数据。顶级容器是一个ViewGroup,一般来说它很可能是DecorView。最后顶级容器在一一去通知它的子元素来保存数据。这是一种典型的委托思想,上层委托下层,比如View的绘制,事件的分发等都用到了这种思想。

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_diy_view);
        //可以直接在onCreate中判断并恢复
        if(savedInstanceState != null){
            String temp_str = savedInstanceState.getString("flag");
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("flag","需要保存的参数");
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        String temp_str = savedInstanceState.getString("flag");
    }
系统配置


横竖屏切换,不重新创建Activity,只需要在AndroidMenifest.xml中的相应的Activity加入:android:configChanges=”orientation|screenSize”即可,代码如下:

<activity 
    android:name=".activitys.DiyViewActivity"
    android:launchMode="singleTop"
    android:configChanges="orientation|screenSize"
activity>

Activity的启动模式

给Activity设置启动模式
第一种:android:launchMode=”singleTask”
第二种:intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
不同点:
1.优先级上,两种方式同时存在的时候以第二种为准。
2.第一张无法直接为Activity设定FLAG_ACTIVITY_CLEAR_TOP标识的效果,而第二种方法无法为Activity指定singleInstance模式。

  • standard:标准模式

注意:
在这种模式下,谁启动这个Activity,那么这个Activity就运行这启动它的那个Activity所在的栈中。所以,当用ApplicationContext去启动standard模式的Activity的时候会报错。因为非Activity类型的Context(如Application)并没有所谓的任务栈。
解决方法:用Activity类型的Context去启动,或给待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位。

/*
这时候启动的Activity实际是以singleTask模式启动的。因为类似CSS的最近原则,当launchMode和setFlags同时存在的时候,以setFlags为准。
*/
Intent intent = new Intent();    intent.setClass(DiyViewActivity.this,SpinnerActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
  • singleTop:栈顶复用模式

如果待启动的Activity已经存在于栈顶则此Activity不会重新创建实例,同时它的onNewIntent()会被回调。通过这个方法的参数我们可以取出当前请求的信息。

 @Override
 protected void onResume() {
     super.onResume();
     log("onResume");
     if(flag){
         Intent intent = new Intent(this,DiyViewActivity.class);
         startActivity(intent);
         flag=flase;
     }
 }
/*
输出: onCreate
输出: onStart
输出: onResume
输出: onPause//Activity会先暂停(不可交互),然后调用onNewIntent()
输出: onNewIntent
输出: onResume
*/

Activity第一启动的时候执行onCreate()—>onStart()—>onResume()等后续生命周期函数,也就时说第一次启动Activity并不会执行到onNewIntent(). 而后面如果再有想启动Activity的时候,那就是执行onNewIntent()—->onResume(). 如果android系统由于内存不足把已存在Activity释放掉了,那么再次调用的时候会重新启动Activity即执行onCreate()—>onStart()—>onResume()等。
注意:
当调用到onNewIntent(intent)的时候,需要在onNewIntent() 中使用setIntent(intent)赋值给Activity的Intent.否则,后续的getIntent()都是得到老的Intent。

  • singleTask:栈内复用模式

这是一种单实例模式,如果栈中已经存在,则会调用onNewIntent。具体一点,例如要启动ActivityA,系统首先会寻找是否存在ActivityA想要的任务栈,如果不存在,则创建,然后创建ActivityA后把它发到该任务栈中。

  • singleInstance:单实例模式。

一种加强的singleTask模式,具有singleTask的所有特性,同时该模式的Activity只能单独位于一个任务栈中。

  • 注意

现在有2个任务栈,前台任务栈为AB,后台任务栈情况为CD,这里假设CD的启动模式均为singTask。现在请求启动D,那么整个后台任务栈都会被切换到前台,这个时候整个后退列表为ABCD,按back键的时候会先弹出D。

你可能感兴趣的:(android)