《Android中高级工程师面试指南 — 基础知识 — Activity》

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jiangguangchao/article/details/78255061

一、Activity的生命周期

1、Android进程优先级

Q: 请简述Android进程的优先级?
A: Android系统往往倾向于延长应用程序的进程,以提高效率,但是当系统内存不足的时候,也需要杀死一些进程来回收资源,而决定杀死哪些进程的一项重要参考指标就是进程的优先级。Android系统根据在进程中在运行的组件及组件的状态,为每一个进程分配了一个优先级等级,优先级最低的进程首先被杀死。
  在Android系统中,进程根据不同的优先级可以分为5个常用等级:前台进程、可见进程、服务进程、后台进程、空进程。Android系统会尽可能高地评估一个进程的优先级,同时一个进程的优先级可能会由于其它进程的依赖而升高。
  前台进程,指用户当前做的事所必须的进程,如果一个进程满足以下下一个条件则被认为是前台进程:
  1、进程持有一个正在与用户交互的Activity。
  2、进程持有一个Service,这个Service处于这几种状态:a、Service与用户正在交互的Activity绑定;b、Service是在前台运行的,即它调用了startForeground();c、Service正在执行它的生命周期回调函数(onCreate(),onStart(),onDestroy())。
  3、进程持有一个BroadcastReceiver,这个BroadcastReceiver正在执行它的 onReceive() 方法。
  前台进程的优先级是最高的,Android系统一般情况下不会杀死一个前台进程。
  可见进程,不含有任何前台的组件,但仍可被用户在屏幕上所见的进程。如果一个进程满足以下下一个条件则被认为是可见进程:
  1、进程持有一个Activity,这个Activity不在前台,但是仍然被用户可见(处于onPause()调用后又没有调用onStop()的状态,比如,前台的activity打开了一个对话框,这样activity就会在其后可见)。
  2、进程持有一个Service,这个Service和一个可见的Activity绑定。
  可见的进程也是很重要的,一般不会被系统销毁,除非为了保证所有前台进程正常运行而不得不杀死可见进程。
  服务进程,如果一个进程中运行着一个service,这个service是通过 startService() 开启的,并且不属于上面两种较高优先级的情况,这个进程就是一个服务进程。
  尽管服务进程没有和用户可以看到的东西绑定,但是它们一般在做的事情是用户关心的,比如后台播放音乐,后台下载数据等。所以系统会尽量维持它们的运行,除非系统内存不足以维持前台进程和可见进程的运行需要。
  后台进程,如果进程不属于上面三种情况,但是进程持有一个用户不可见的activity(activity的onStop()被调用,但是onDestroy()没有调用的状态),就认为进程是一个后台进程。
  后台进程不直接影响用户体验,系统会为了前台进程、可见进程、服务进程而任意杀死后台进程。
  通常会有很多个后台进程存在,它们会被保存在一个LRU列表中,这样就可以确保用户最近使用的Activity最后被销毁。
  空进程 如果一个进程不包含任何活跃的应用组件,则认为是空进程。例如:一个进程当中已经没有数据在运行了,但是内存当中还为这个应用驻留了一个进程空间。 保存这种进程的唯一理由是为了缓存的需要,为了加快下次要启动这个进程中的组件时的启动时间。
  空进程通常最先被系统杀死。

2、Activity的四种状态

Q:Activity有哪几种状态?
A: 每个activity在其生命周期内最多会经历四种状态:运行状态、暂停状态、停止状态、销毁状态。
  运行状态(running):activity处于任务栈的栈顶,此时它处于可见并可和用户交互的激活状态。
  暂停状态(paused):activity不再处于栈顶,但是仍然可见,这时activity就处于暂停状态。比如,activity被另一个透明或者Dialog样式的activity覆盖。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,它仍然可见,但它已经失去了焦点,故不可与用户交互。
  停止状态(stopped):activity不再处于栈顶且完全不可见的时候,这时activity就处于停止状态。这种状态下这个activity是否继续存活取决于系统内存是否充足。
  销毁状态(destroyed): activity被杀掉以后或者被启动以前,这时activity处于销毁状态。这时activity已从activity任务栈中移除,需要重新启动才可以显示和使用。

3、Activity的生命周期

  以下这张图得记住!
Activity生命周期

Q:请简述Activity的生命周期?
A: Activity常用的生命周期回掉函数包括:onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()、onRestart()。
  onCreate():create表示创建,这是Activity生命周期的第一个方法,它的作用是进行Activity的一些初始化工作,比如使用setContentView加载布局,对一些控件和变量进行初始化等。
  onStart():start表示启动,这时activity正在被启动,即将开始,activity正在从不可见到可见,但此时activity还在后台,还无法与用户交互。
  onResume():resume表示继续、重新开始,这时activity已经可见,且可以和用户交互,此时activity一定是处于任务栈的栈顶,一定是在前台。
  onPause():pause表示暂停,当activity要跳到另一个activity或应用正常退出时都会执行这个方法
  onStop():stop表示停止,此时activity已经不可见了,但是activity对象还在内存中,没有被销毁。
  onDestroy():destroy表示毁灭, 此时activity正在被销毁,可以做回收工作,资源释放,解除绑定等。
  onRestart():表示activity正在重新启动,一般情况,当activity从不可见变成可见的时候,该方法就会被调用。
  通常情况下,当我们启动activity,系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,activity进入运行状态。如果当前activity被其他activity覆盖或被锁屏,系统会调用当前activity的onPause方法,暂停当前activity的执行。如果当前activity由被覆盖状态回到前台或解锁屏,这时系统会调用当前activity的onResume方法,再次进入运行状态。如果当前activity转到新的activity界面或按Home键回到主屏,当前activity退居后台,则系统会先调用当前activity的onPause方法,然后调用onStop方法,当前activity进入停滞状态。如果这时用户后退回到此activity,则系统会先调用此activity的onRestart方法,然后调用onStart方法,最后调用onResume方法,此activity再次进入运行状态。如果当前Activity处于被覆盖状态或者后台不可见状态,这时系统内存不足并且杀死了当前的activity,而后用户退回当前activity,则再次调用当前activity的onCreate方法、onStart方法、onResume方法,进入运行状态。如果用户退出当前activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前activity。

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

Q:在系统配置发生变化时,比如横竖屏发生了变化,请简述此时Activity的生命周期以及如何解决?
A: 在默认情况下,当系统配置发生改变后,如果我们的Activity不做特殊处理,Activity就会被销毁并重新创建。
  Activity被销毁时,它的onPause()、onStop()和onDestory()方法均会被调用,同时系统配置发生改变属于异常情况,这个时候系统会调用Activity的onSaveInstanceState()方法来保存当前Activity的状态。onSaveInstanceState()方法的调用时机是在onStop()方法之前,它和onPause()没有既定的时序关系,它既可能在onPause()之前调用,也可能在onPause()之后调用。(注:这个方法只会出现在Activity被异常终止的情况下,正常情况下系统不会回调这个方法,异常情况也包括Activity被系统杀死等)。
  Activity被重新创建时,系统会调用Activity的onRestoreInstanceState()方法,并且把Activity销毁时onSaveInstanceState()方法所保存的Bundle对象作为参数同时传递给onRestoreInstanceState()和onCreate()方法,这个时候我们就可以取出之前保存的数据并恢复。(当我们恢复数据时,可以选择onRestoreInstanceState()或者onCreate(),二者的区别是:onRestoreInstanceState()一旦被调用,其参数Bundle savedInstanceState 一定是有值的,我们不用额外的判断是否为空,但是onCreate()不行,onCreate()如果是正常启动的话,其参数Bundle savedInstanceState为null,所以必须额外判断,这两个方法任意一个都可以进行数据恢复,官方文档建议采用onRestoreInstanceState()去恢复数据。从时序来说,onRestoreInstanceState()的调用时机在onStart()之后)
  同时,在onSaveInstanceState()和onRestoreInstanceState()方法中,系统自动为我们做了一定的恢复工作,当Activity在异常情况下需要重新创建时,系统会默认为我们保存当前Activity的视图结构,并且在Activity重启后为我们恢复这些数据,比如文本框中用户输入的数据,ListView滚动的位置等。这些View相关的状态系统都能够默认为我们恢复。(注:和Activity一样,每个View都有onSaveInstanceState()和onRestoreInstanceState()这两个方法)
  系统配置中有很多内容,如果当某项内容发生改变后,我们不想系统重新创建Activity,可以给Activity设置configChanges属性。比如不想让Activity在屏幕旋转的时候重新创建,就可以给configChanges属性添加orientation这个值: android:configChanges=”orientation”。当SDK版本大于13时,还需增加srceenSize。

二、Android的任务栈

Q:请简述Android的任务栈机制?
A: 在Android系统中,任务是一个Activity的集合,它使用栈的方式来管理其中的Activity,这个栈又被称为返回栈(back stack),栈中Activity的顺序就是按照它们被打开的顺序依次存放的,是一个典型的后进先出的数据结构。
  当一个Activity启动了另外一个Activity的时候,新的Activity就会被放置到返回栈的栈顶并将获得焦点。前一个Activity仍然保留在返回栈当中,但会处于停止状态。当用户按下Back键的时候,栈中最顶端的Activity会被移除掉,然后前一个Activity则会得重新回到最顶端的位置。默认情况下,一个Activity在任务栈中可以被实例化多次。
  当用户通过Home键离开一个任务时,该任务会进入后台,并且返回栈中所有的Activity都会进入停止状态。系统会将这些Activity的状态进行保留,这样当用户下一次重新打开这个应用程序时,就可以将后台任务直接提取到前台,并将之前最顶端的Activity进行恢复。
  如果用户将任务切换到后台之后过了很长一段时间,系统会将这个任务中除了最底层的那个Activity之外的其它所有Activity全部清除掉。当用户重新回到这个任务的时候,最底层的那个Activity将得到恢复。
  上述则是Android默认的任务栈管理机制,我们想改变这种默认方式,可以在manifest文件中设置activity元素的属性,或者是在启动Activity时配置Intent的flag。在activity元素的属性中,我们可以配置taskAffinity、launchMode、allowTaskReparenting、clearTaskOnLaunch、alwaysRetainTaskState、finishOnTaskLaunch等,在Intent当中,常用的flag包括:FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP、FLAG_ACTIVITY_SINGLE_TOP。

三、Activity的启动模式

Q:请简述Activity的四种启动模式?
A: 当我们在manifest文件中定义Activity的时候,可以通过activity元素的launchMode属性来指定这个Activity应该如何与任务进行关联。launchMode也就是启动模式,一共分为四种:
  ”standard”(默认启动模式):如果不指定launchMode属性,则自动就会使用这种启动模式。这种启动模式表示每次启动该Activity时系统都会为创建一个新的实例,并且总会把它放入到当前的任务当中。声明成这种启动模式的Activity可以被实例化多次,一个任务当中也可以包含多个这种Activity的实例。
  ”singleTop”(栈顶复用模式):如果要启动的这个Activity在当前任务中已经存在了,并且还处于栈顶的位置,那么系统就不会再去创建一个该Activity的实例,而是调用栈顶Activity的onNewIntent()方法。声明成这种启动模式的Activity也可以被实例化多次,一个任务当中也可以包含多个这种Activity的实例。
  ”singleTask”(栈内复用模式):如果现有任务当中已经存在一个该Activity的实例了,那么系统就不会再创建一次它的实例,而是会直接调用它的onNewIntent()方法。声明成这种启动模式的Activity,在同一个任务当中只会存在一个实例。
  ”singleInstance”(单例模式):这种启动模式和”singleTask”有点相似,只不过系统不会向声明成”singleInstance”的Activity所在的任务当中再添加其它Activity。也就是说,这种Activity所在的任务中始终只会有一个Activity,通过这个Activity再打开的其它Activity也会被放入到别的任务当中。

  注:本篇博客开始,后期会推出《Android中高级工程师面试指南》系列博客,该系列博客收录一些Android中高级工程师面试时经常遇到的面试题,内容包括:Android基础知识面试讲解、消息机制和多线程面试讲解、网络协议和网络框架面试讲解、View相关面试讲解、性能优化面试讲解、设计模式和架构设计面试讲解、Android源码相关面试讲解、前沿技术面试讲解。希望能够帮助各位读者找到心仪的工作。
  注:在Android中高级工程师面试的时候,基础知识一般会问的比较细,面试官会通过一些技术细节来判断你的技术水平,所以基础知识这部分一定要好好准备,尤其是一些细节。
  注:能力有限,水平一般,如果文章中有错误,欢迎大家留言指正。如果大家觉得文章写的不错,对技术水平的提升还有点帮助,扫描下面的二维码,打赏笔者一瓶水钱也是极好的~~~
这里写图片描述

猜你喜欢

转载自blog.csdn.net/jiangguangchao/article/details/78255061