Android面试系列文章2018之Android部分Activity篇
Android面试系列2018知识总结:
http://blog.csdn.net/ClAndEllen/article/details/79257663
1.Activity生命周期
1.1 Activity的4种状态
running/paused/stopped/killed
running:当前Activity正处于运行状态,指的是当前Activity获取了焦点。
paused:当前Activity正处于暂停状态,指的是当前Activity失去焦点,此时的Activity并没有被销毁,内存里面的成员变量,状态信息等仍然存在,当然这个Activity也仍然可见,但是焦点却不在它身上,比如被一个对话框形式的Activity获取了焦点,或者被一个透明的Activity获取了焦点,这都能导致当前的Activity处于paused状态。
stopped:与paused状态相似,stopped状态的Activity是完全不可见的,但是内存里面的成员变量,状态信息等仍然存在,但是也没有被销毁。
killed:已经被销毁的Activity才处于killed状态,它的内存里面的成员变量,状态信息等都会被一并回收。
1.2 Activity的生命周期分析
Activity启动–>onCreate()–>onStart()–>onResume()
点击home键回到桌面–>onPause()–>onStop()
再次回到原Activity时–>onRestart()–>onStart()–>onResume()
退出当前Activity时–>onPause()–>onStop()–>onDestroy()
想了解Activity生命周期的详情请看以下链接:
https://www.jianshu.com/p/f9da7ecded20?utm_campaign=maleskine&utm_content=note&utm_medium=writer_share&utm_source=weibo
1.3 进程的优先级
前台>可见>服务>后台>空
前台:与当前用户正在交互的Activity所在的进程。
可见:Activity可见但是没有在前台所在的进程。
服务:Activity在后台开启了Service服务所在的进程。
后台:Activity完全处于后台所在的进程。
空:没有任何Activity存在的进程,优先级也是最低的。
2.Android任务栈
任务栈与Activity的启动模式密不可分,它是用来存储Activity实例的一种数据结构,Activity的跳转以及回跳都与这个任务栈有关。详情请看下面的Activity的启动模式。
3.Activity的启动模式
Activity的启动模式,你在初学期间一定很熟悉了吧!不管你是否熟悉还是不熟悉,跟随笔者的思路把Activity的启动模式整理一遍:
问题1:Activity为什么需要启动模式?
问题2:Activity的启动模式有哪些?特性如何
问题3:如何给Activity选择合适的启动模式
问题1:Activity为什么需要启动模式?
我们都知道启动一个Activity后,这个Activity实例就会被放入任务栈中,当点击返回键的时候,位于任务栈顶层的Activity就会被清理出去,当任务栈中不存在任何Activity实例后,系统就回去回收这个任务栈,也就是程序退出了。这只是对任务栈的基本认识,深入学习,笔者会在之后文章中提到。那么问题来了,既然每次启动一个Activity就会把对应的要启动的Activity的实例放入任务栈中,假如这个Activity会被频繁启动,那岂不是会生成很多这个Activity的实例吗?对内存而言这可不是什么好事,明明可以一个Activity实例就可以应付所有的启动需求,为什么要频繁生成新的Activity实例呢?杜绝这种内存的浪费行为,所以Activity的启动模式就被创造出来去解决上面所描述的问题。
问题2:Activity的启动模式有哪些?特性如何
Activity的启动模式有4种,分别是:standard,singleTop,singleTask和singleInstance。下面一一作介绍:
1.系统默认的启动模式:standard
标准模式,这也是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否存在。被创建的实例的生命周期符合典型情况下的Activity的生命周期。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity的任务栈中。比如Activity A启动了Activity B(B是标准模式),那么B就会进入到A所在的任务栈中。有个注意的地方就是当我们用ApplicationContext 去启动standard模式的Activity就会报错,这是因为standard模式的Actiivty默认会进入启动它的Activity所属的任务栈中,但是由于非Activity类型的Context(如ApplicationContext)并没有所谓的任务栈,所以这就会出现错误。解决这个问题的方法就是为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样启动的时候就会为它创建一个新的任务栈,这个时候启动Activity实际上以singleTask模式启动的,读者可以自己仔细体会。
2.栈顶复用模式:singleTop
在这种模式下,如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法被回调,通过此方法的参数我们可以取出当前请求的信息。需要注意的是,这个Activity的onCreate,onStart不会被系统调用,因为它并没有发生改变。如果新的Activity已经存在但不是位于栈顶,那么新的Activity仍然会重新重建。举个例子,假设目前栈内的情况为ABCD,其中ABCD为四个Activity,A位于栈低,D位于栈顶,这个时候假设要再次启动D,如果D的启动模式为singleTop,那么栈内的情况依然为ABCD;如果D的启动模式为standard,那么由于D被重新创建,导致栈内的情况为ABCDD。
3.栈内复用模式:singTask
这是一种单例实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,和singleTop一样,系统也会回调其onNewIntent。具体一点,当一个具有singleTask模式的Activity请求启动后,比如Activity A,系统首先寻找任务栈中是否已存在Activity A的实例,如果已经存在,那么系统就会把A调到栈顶并调用它的onNewIntent方法,如果Activity A实例不存在,就创建A的实例并把A压入栈中。举几个栗子:
- 比如目前任务栈S1的情况为ABC,这个时候Activity D以singleTask模式请求启动,其所需的任务栈为S2,由于S2和D的实例均不存在,所以系统会先创建任务栈S2,然后再创建D的实例并将其投入到S2任务栈中。
- 另外一种情况是,假设D所需的任务栈为S1,其他情况如同上面的例子所示,那么由于S1已经存在,所以系统会直接创建D的实例并将其投入到S1。
- 如果D所需的任务栈为S1,并且当前任务栈S1的情况为ADBC,根据栈内复用的原则,此时D不会重新创建,系统会把D切换到栈顶并调用其onNewIntent方法,同时由于singleTask默认具有clearTop的效果,会导致栈内所有在D上面的Activity全部出栈,于是最终S1中的情况为AD。
通过以上3个例子,你应该能比较清晰地理解singleTask的含义了。
4.单实例模式:singleInstance
这是一种加强的singleTask模式,它除了具有singleTask模式所有的特性外,还加强了一点,那就是具有此种模式的Activity只能单独位于一个任务栈中,换句话说,比如Activity A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了。
- 总结
上面介绍了4种启动模式,这里需要指出一种情况,我们假设目前有2个任务栈,前台任务栈的情况为AB,而后台任务栈的情况为CD,这里假设CD的启动模式均为singleTask。现在请求启动D,那么整个后台任务栈都会被切换到后台,这个时候整个后退列表变成了ABCD。当用户按back键的时候,列表中的Activity会一一出栈,如下图1所示:
如果不是请求的D而是请求的C,那么情况就不一样了,如下图2所示:
如何指定活动的启动模式呢?在AndroidManifest.xml文件当注册活动的代码中去指定
比如:我要把MainActivity活动的启动模式指定为singleInstance模式
4.scheme跳转协议
Android中的scheme是一种页面内跳转协议,通过自定义scheme协议,可以非常方便的跳转到app中的各个页面,通过scheme协议,服务器可以定制化告诉app跳转到哪个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转到相应页面等等。
如果你之前没用过,那么请看以下链接进行学习吧:
http://blog.csdn.net/qq_23547831/article/details/51685310