读书小记——Activity

Activity读书小记

首先是Activity的生命周期,简单回顾:

  1. onCreate:创建。

  2. onStart:可见不可交互,即未位于前台。

  3. onResume:可见可交互,即已位于前台。

  4. onPause:可见但不可交互。

  5. onStop:停止,不可见不可交互

  6. onDestroy:销毁。

  7. onReStart:重新启动。即执行完onPause和onStop但未执行onDestroy,被重新启动时执行。

关于生命周期的两个问题:

区分
onStart onStop 可见与不可见
onResume onPause 可交互与不可交互
从Activity 1 启动 Activity 2的过程

首先是1不可与用户交互,执行onPause后,1可见但不可交互,然后才会执行2的创建,即onCreate、onStart、onResume,当2可见可交互后,相应的1不再位于前台,不再能交互,即1的onStop。

所以为了保证Activity启动的效率,不能再Activity的onPause、onStorp中执行耗时性动作。


Activity的异常情况下的生命周期

Activity异常销毁,数据的保存:onSaveInstanceState、onReStoreInstanceState
问题:onSaveInstanceState在什么情况下被执行???
onSaveInstanceState的调用在onStop之前是一定的,但与onPause之间的时序关系就不一定了,可能是在onPause之前,也可能在onPause之后。

1、首先在Activity中,onSaveInstanceState的执行代码如下,onSaveInstanceState在performSaveInstanceState中被执行:

final void performSaveInstanceState(Bundle outState) {
      onSaveInstanceState(outState);
      saveManagedDialogs(outState);
      mActivityTransitionState.saveState(outState);
      storeHasCurrentPermissionRequest(outState);
      if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
  }

2、performSaveInstanceState的调用是通过ActivityThread类中callCallActivityOnSaveInstanceState方法被执行到的,中间一步此处先忽略。callCallActivityOnSaveInstanceState代码片段如下:

private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
      r.state = new Bundle();
      r.state.setAllowFds(false);
      if (r.isPersistable()) {
          r.persistentState = new PersistableBundle();
          mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
                  r.persistentState);
      } else {
          mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
      }
  }

3、在ActivityThread中callCallActivityOnSaveInstanceState被多个地方调用,此处主要看两个地方:performPauseActivity和performStopActivity。此处两个内部正是回调了Activity对应的onPause和onStop方法,当然在其中还包含了其他的一些操作,onSaveInstanceState就包含在其中。

先看下performPauseActivity,performStopActivity内与之类似:

if (!r.activity.mFinished && saveState) {
        callCallActivityOnSaveInstanceState(r);
    }
    //Activity的onPause方法在该方法内部被调用
    performPauseActivityIfNeeded(r, reason);
    //performStopActivityIfNeeded(r, reason);

此处可以看出在执行onPause之前是有可能执行callCallActivityOnSaveInstanceState方法的,即onSaveInstanceState方法,callCallActivityOnSaveInstanceState的方法执行需要满足两个条件,一个是flag—mFinished,是否执行了finish方法,所以这也解释了为什么onBackPressed和执行finish方法正常关闭的Activity不会执行onSaveInstanceState方法;另外一个条件是flag—saveState(看名字就知道,表示是不是需要存储数据的状态)。

4、onPause、onStop中执行callCallActivityOnSaveInstanceState的主要区别就在saveState,在performPauseActivity中,saveState最终的值取决于函数ActivityClientRecord的isPreHoneycomb方法,该方法判断的是当前Applicatio的targetSdkVersion目标编译版本是否大于Android3.0,即Android3.0版本前才会存在onSaveInstanceState的执行在onPause之前。而performStopActivity中的saveState则直接传递进来的值为true,也就是在执行onStop之前如果Activity未执行finish方法的话,onSaveInstanceState方法就会被调用,即异常销毁的状态。

public boolean isPreHoneycomb() {
        if (activity != null) {
            return activity.getApplicationInfo().targetSdkVersion
                  < android.os.Build.VERSION_CODES.HONEYCOMB;
        }
        return false;
    }

onReStoreInstanceState则是在Activity异常销毁被再次创建时调用,数据的保存和恢复通过Bundle载体完成,onReStoreInstanceState方法和onCreate方法均会携带onSaveInstanceState调用时保存的数据,但onReStoreInstanceState被调用bundle不会为空,onCreate在正常情况下bundle为null,所以在onCreate内恢复数据则需要进行数据的检查校验。

针对一些特殊配置的变化,不想Activity重新创建的问题,例如sim卡变更、横竖屏切换、语言切换等等,可以通过menifest生命activity时配置configChanges标签属性来防止activity重启,常见的sim卡变更(mcc、mnc);横竖屏变更(orientation)、语言变更(locale)等,对应的可以通过充血activity的onConfigurationChanged方法来监听这行config变更需要处理的一些操作。

Activity的启动模式

1、standard:标准模式,每次启动Activity都会创建一个新的Activity实例。新启动的Activity会被加入到原Activity的栈中,所以通过ApplicationContext启动standard的Activity会报错,提示Activity需要ACTIVITY_NEW_TASK flag,因为ApplicationContext没有任务栈。

2、singleTop:栈顶单例模式。需要启动的Activity位于栈顶,则不需要重新创建,否则重新创建。

3、singleTask:栈内单例模式。只要当前Activity栈中存在需要启动的Activity,则不会重新创建,否则重新创建。

4、singleInstance:全栈单例模式。单独位于一个任务栈。

TaskAffinity:任务相关性。

TaskAffinity与singleTask的Activity结合使用,可以指定Activity所属的任务栈。

例如:存在Application 1,Activity A1已经启动,ActivityB1属于App1,ActivityB1为上述TaskAffinity指定了App1包名与singleTask的Activity

当App2内Activity A2启动App1 ActivityB1时,正常为ActivityB1与App2 Activity A2为同一个栈,但ActivityB1指定了栈为App1包名,此时将App2 home键后再进入,发现并不是ActivityB1,而打开App1,发现栈顶为ActivityB1。

应用:当两个App属于从属关系,App1启动,App2在其他应用启动时,我们希望App2依赖于App1,而不是独立存在的栈时,可以设置App2的相关Activity的TaskAffinity为App1的包名。

TaskAffinityh和allowTaskReparenting(允许重定向父级)

在这种情况下,Activity 可以从其启动的任务栈移动到与其具有关联的任务栈(如果该任务栈出现在前台)。

对比:TaskAffinity与singleTask的Activity结合使用,TaskAffinity所属的任务栈已经存在,才会将Activity移到对应设置的栈,不存在则依然停留在当前栈。

而TaskAffinityh和allowTaskReparenting,则是当Activity设置的栈出现在前台时,可以将已经存在的Activity重新移动到设置的栈中。

你可能感兴趣的:(Android)