Activity知识点总结

这篇文章本来作为AndroidDeveloper的学习笔记,当初对Android是一无所知,现在的程度是粗浅的看了AMS源码,且读了《Android群英准》和《Android开发艺术探索》后的总结。

Introduction to Activities

Activities是Android四大组件之一,用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。 每个 Activity 都会获得一个用于绘制其用户界面的窗口。窗口通常会充满屏幕,但也可小于屏幕并浮动在其他窗口之上。

在manifest.xml中的写法为:

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

Activity Lifecycle

  • Entire lifetime (onCreate()-> onDestroy())
  • Visible lifetime(onStart()-> onStop())
  • Foreground lifetime(onResume()-> onPause())

整个生命周期和前台生命周期很好理解,那么可见生命周期和前台生命周期有什么区别呢?因为屏幕上可以存在多个Activity,比如在一个Activity1中打开了一个对话框(这个对话框也是一个Activity,记为Activity2),此时用户既可以看到Activity1也可以看到Activity2,此时Activity2处于前台生命周期,Activity1处于可见生命周期。如下图所示,当点击START DIALOGACTIVITY按钮时,MainActivity会调用onPause()方法,而不是onStop()。

这里写图片描述

完整的生命周期示意图如下图所示:

这里写图片描述
这里提出一个问题:(也是我面试被问到的)
假设当前Activity为A,如果这时用户打开一个新的Activity B,那么B的onResume和A的onPause哪个先执行呢?
先说答案:A先onPause,B才能onResume
源码中找答案:
mResumedActivity表示当前处于resume状态的Activity,


		/**
     	* Current activity that is resumed, or null if there is none.
     	*/
    	ActivityRecord mResumedActivity = null;
    	/*
    	此处省略
    	*/
        // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
        // to be paused, while at the same time resuming the new resume activity only if the
        // previous activity can't go into Pip since we want to give Pip activities a chance to
        // enter Pip before resuming the next activity.
        final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
                && !lastResumedCanPip;

		//Pause all activities in either all of the stacks or just the back stacks.
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }

        /// M: onBeforeActivitySwitch @{
        mService.mAmsExt.onBeforeActivitySwitch(mService.mLastResumedActivity, next, pausing,
                next.getActivityType());
        /// M: onBeforeActivitySwitch @}

        if (pausing && !resumeWhilePausing) {
            if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                    "resumeTopActivityLocked: Skip resume: need to start pausing");
            // At this point we want to put the upcoming activity's process
            // at the top of the LRU list, since we know we will be needing it
            // very soon and it would be a waste to let it get killed if it
            // happens to be sitting towards the end.
            if (next.app != null && next.app.thread != null) {
                mService.updateLruProcessLocked(next.app, true, null);
            }
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            if (lastResumed != null) {
                lastResumed.setWillCloseOrEnterPip(true);
            }
            return true;
        } else if (mResumedActivity == next && next.isState(RESUMED)
                && mStackSupervisor.allResumedActivitiesComplete()) {
            // It is possible for the activity to be resumed when we paused back stacks above if the
            // next activity doesn't have to wait for pause to complete.
            // So, nothing else to-do except:
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        }

Tasks and Back Stack

Android中的Activity是可以层叠的,没启动一个新的Activity,就会覆盖在原有的Activity之上,然后点击Back键会销毁最上面的Activity,下一个Activity就会重新显示出来。可以思考一下这种层叠的结构怎么实现?没错,就是栈,First in Last out,假设启动顺序为Activity1 -> Activity2 -> Activity3,那么栈中的结构是,Activity3在顶部,Activity1在底部。

When the user presses the Back button:
这里写图片描述

在Android中,是使用Task来管理Activity的,一个Task就是一个这样的栈结构,这个栈也被称为Back Stack。

launchMode:

  • standard(the default mode):每启动一个新的Activity,都会创建一个新的实例
  • singleTop:如果启动的Activity已经在栈顶,则不会再创建实例
  • singleTask:只要启动的Activity在栈里面,则不会再创建实例,并且这个Activity之上的所有Activity全部出栈,如果没有在栈里面,则创建实例
  • singleInstance:这种模式是为了不同的APP能共享Activity,启动的Activity会在一个单独的Back Stack中,并保证不再有其他Activity实例进入,也是说这个Back Stack只有这一个Activity。

这里我画了一个示例图:

这里写图片描述
关于启动模式,基本的知识就如上述写的,读过《Android群英传》和《Android开发艺术探索》后总结一下两本书中对Activity部分的讲解。

standard

  • 每启动一个Activity都会重新创建一个新的实例,不管这个实例是否存在
  • 谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity所在的栈中。比如Activity A启动了Activity B(standard模式),那么B就进入到A的栈中。

singleTop

  • 新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建(如果不是位于栈顶,新的Activity会重新创建),同时它的onNewIntent方法会被回调。
  • 以singleTop启动的Activity的onCreateonStart不会被系统调用,因为它没有发生改变。

singleTask

  • 只要Activity在一个栈中存在,那么多次启动此Activity都不会创建实例

For example:
No1
S1:ABC
Activity D以SingleTask启动,所需任务栈为S2(S2未创建)
系统会先创建S2,然后创建D的实例压入S2中

No2
S1:ABC
Activity D以SingleTask启动,所需任务栈为S1
系统直接创建D的实例压入S1中

No3
S1:ADBC
Activity D以SingleTask启动,所需任务栈为S1
系统不会创建D的实例,将D切换到栈顶,并且clearTop,即D上面的Activity(BC)全部出栈,最终S1的情况为AD

No4
在这里插入图片描述
如图所示
Back Stack:12
Background Task:YX
Activity Y以singleTop启动,那么Background Task会切换到Back Stack,整个后退列表变成了YX21,用户按back键的时候,列表中的Activity一一出栈。

singleInstance

  • 具有singleTask模式的所有特性
  • 此模式启动的Activity只能单独地位于一个任务栈中

面试中常见问题:(掌握的越深越好)

  • Activity启动模式
  • Activity启动过程
  • Activity生命周期
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值