1. Activity生命周期和启动模式

生命周期

13671484-9923b6bb17ad2078.png
生命周期流程图
典型情况下生命周期(右边的流程)
  • 单击打开应用


    13671484-60880ff1e0d0a074.png
    打开应用
  • 点击Back键,退出应用


    13671484-9eda4944f5989f5b.gif
    GIF.gif

    结果输出日志为下图


    13671484-f30f117f738f9453.png
    2018-11-23_224758.png
  • 切换出去,然后再返回,只要切换的速度够快,就可以实现,在将activity放入后台(onStop)之前,返回。其实可以从动图中看见,这个activity几乎可以一直可见


    13671484-96e4d35e38b2b192.gif
    GIF.gif

    13671484-fe083e790a302550.png
    2018-11-23_225801.png

但是如果稍微慢一点,执行同样的操作,系统就会将其放入后台(onStop)


13671484-73fcbbd5d03e0237.png
慢一点后输出的日志

启动新的activity顺序:调用instrumentation,然后instrumentation向AMS发送开启新activity的请求,AMS内部有一个activitystack,存有activity状态的栈,其会先onPause栈顶的activity,然后开始新的activity

异常情况下生命周期(右边的流程)

补充内容


  • onSaveInstanceState:保存数据
  1. 用户主动点击Back键,即主动销毁activity时,不执行onSaveInstanceState方法
    其他异常销毁activity情况,是需要执行onSaveInstanceState方法的,如屏幕从竖屏切换到横屏
  2. 这个activity有可能被销毁的情况下,也会调用,如按home键返回桌面、启动一个新的Activity等(如果内存不够用,就有可能销毁之前的activity)
  • onRestoreInstanceState:恢复数据
    当第一个activity由于内存不足被销毁了,执行了onSaveInstanceState方法后,由于不是用户主动销毁的,会调用onRestoreInstanceState

  • 资源配置改变,导致Activity被杀死 并重新创建(横屏切换到竖屏)
    可以配置资源配置:android:configChanges="orientation":当屏幕切换时,activity不重新创建。但是当资源配置改变时,需要执行onConfigurationChanged方法

  • 资源内存不足导致优先级低的应用被杀死
    正在和用户交互的activity >>> 可见但非前台(比如弹窗(非ProgressDialog)后,activity可见,但被放入后台了)>>> 不可见、被放入后台(onStop)

启动模式

taskAffinity:任务相关性,标识一个Activity所需要的栈的名字,默认所有任务栈名字为应用包名,只对栈内复用模式单实例模式有用,其他两个都是默认只识别启用者(执行startActivity)的堆栈

1.standard:标准模式

每启动一个Activity,就会创建一个实例
谁启动了Activity(标准模式),被启动的Activity就会进入启动者的堆栈中

但是,如果是启动Activity这个活动的类的类型为Context(如:getApplicationContext获取),就会报错android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?,这个报错提示你,需要提供一个flag:FLAG_ACTIVITY_NEW_TASK,表示创建新的任务栈来运行这个activity,这个时候启动的其实是sigleTask模式启动的
context启用activity

获取全局Context(还需要在Mainifest中填写Application:name=".getGlobalContext "):
public class getGlobalContext extends Application {
    private static Context context;

    @Override
    public void onCreate() {
        context = getApplicationContext();
        super.onCreate();
    }

    public static Context getContext(){
        return context;
    }
}

启用:
Context = getGlobalContext.getContext();
context.startActivity(new Intent("secondactivity"));
2. singleTop:栈顶复用模式

如果要启用的Activity实例已经位于栈顶,那么这个Activity不会再创建了,同时其onNewIntent 方法会被回调,同时可以获取请求的数据
当然,如果没在栈顶,在栈内其他地方还是可以被创建的,并且这个activity实例只会进入启动者的堆栈中

        <activity android:name=".secondActivity"
//给这个活动的taskAffinity属性赋值:即定义一个新的相关联的任务栈名称
            android:taskAffinity="com.app.typicallifecycle.secondTaskStack"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="secondactivity" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

当从MainActivity启动secondActivity时,adb shell dumpsys activity查看堆栈信息,可以看见在同一任务栈下

    Running activities (most recent first):
      TaskRecord{4a91ab14 #21 A=com.app.typicallifecycle U=0 sz=2}
        Run #1: ActivityRecord{4a989564 u0 com.app.typicallifecycle/.secondActivity t21}
        Run #0: ActivityRecord{4a963ca4 u0 com.app.typicallifecycle/.MainActivity t21}
3. singleTask:栈内复用模式(单例模式)

Activity B请求启动后,会先找想要的栈(先看taskAffinity的值,如果没有这个值,再看启动者),如果没有就会创建一个新的栈,并放入。如果有找到想要的栈,先看栈内是否有其实例,如果有将栈内该实例调到栈顶,并回调onNewIntent 。如果没有则压入栈

4. singleInstance:单实例模式

加强版的栈内复用模式。当一个新的Activity请求启动时,创建一个新的栈并压入该Activity,并且这个栈中有且只有这个模式下的Activity。如果同一Activity请求启动,那么只有等这个特殊任务栈被销毁才行

如果没有给需要启动的activity(单实例模式),设置taskAffinity属性,在不同任务栈下
    Running activities (most recent first):
      TaskRecord{4a8c3cbc #20 A=com.app.typicallifecycle U=0 sz=1}
        Run #1: ActivityRecord{4a8e6b34 u0 com.app.typicallifecycle/.secondActivity t20}
      TaskRecord{4a92525c #19 A=com.app.typicallifecycle U=0 sz=1}
        Run #0: ActivityRecord{4a8bdd08 u0 com.app.typicallifecycle/.MainActivity t19}

上面四种启动模式,介绍的是单一任务栈,下面开始介绍多个栈下的调用关系

当未开启任何应用时,存在一个栈Stack #0,可以通过adb shell dumpsys activity查看,可以这个栈看为系统栈,这个栈只存有少数的activity,例如:主界面、活动列表(存有最近打开的应用,即使销毁了,也可以通过此来重新创建)

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
  Stack #0:

打开任意应用,都会压入另一个栈Stack #1,里面有很多任务栈(Task id )

  Stack #1:
    Task id #64
      TaskRecord{4a913c8c #64 A=com.app.typicallifecycle U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.app.typicall
ifecycle/.MainActivity }
        Hist #0: ActivityRecord{4a8bd970 u0 com.app.typicallifecycle/.MainActivity t64}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.app.typi
callifecycle/.MainActivity bnds=[431,618][572,848] }
          ProcessRecord{4a8e6b88 9229:com.app.typicallifecycle/u0a30}

    Task id #63
      TaskRecord{4a8e281c #63 A=com.tencent.mm U=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.tencent.mm/.
ui.LauncherUI (has extras) }
        Hist #0: ActivityRecord{4a8f1728 u0 com.tencent.mm/.ui.LauncherUI t63}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.tencent.
mm/.ui.LauncherUI bnds=[290,618][431,848] (has extras) }
          ProcessRecord{4a8d12fc 9076:com.tencent.mm/u0a28}

    Running activities (most recent first):
      TaskRecord{4a913c8c #64 A=com.app.typicallifecycle U=0 sz=1}
        Run #1: ActivityRecord{4a8bd970 u0 com.app.typicallifecycle/.MainActivity t64}
      TaskRecord{4a8e281c #63 A=com.tencent.mm U=0 sz=1}
        Run #0: ActivityRecord{4a8f1728 u0 com.tencent.mm/.ui.LauncherUI t63}
  • 即使将activityA加入Stack #0栈中,如果从activityA中开启一个acitivityB,并且acitivityB的任务栈不在Stack #0中,那么acitivityB所在的任务栈会加入Stack #1

  • 实例1: 任务栈之间的混用

    13671484-95a41309d5f27d3d.png
    绘图1.png

  1. 开启应用typicallifecycle,创建了第一个任务栈(com.app.typicallifecycle),并将第一个activity压入栈中,当开启第二个activity时,由于下面的代码配置,会将这个secondActivity放入已经开启的微信的栈中,如上面流程图所示,然后按返回键会返回到微信的界面
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".secondActivity">
            android:taskAffinity="com.tencent.mm"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="secondactivity" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
13671484-78c7c66e9577ec14.gif
任务栈之间的混用

也可以同样的方法用在系统栈Stack #0,这样会直接返回到主界面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值