Activity相关面试基础点

1.Activity的affinity

  1. affinity是Activity内部的一个属性(在Manifest中对应属性为taskAffinity)。默认情况下,拥有相同affinity的Activity属于同一个Task。
  2. Task也有affinity属性,它的属性由根Activity决定(创建Task时,第一个被压入栈的Activity实例)
  3. 默认情况下,所有的Activity的affinity都从Application继承。也就是说Application同样有affinity属性。Application默认的affinity属性为Manifest的包名。

2.Activity 的启动模式

Activity的启动模式分为四种,standard,singleTop,singleTask,singleInstance

  • standard:默认模式,每次启动都会创建一个新的Activity实例,不管当前任务栈中是否已经存在实例,都会创建。

  • singleTop:栈顶模式,当我们创建一个新的Activity的实例的时候,如果当前Activity在任务栈的栈顶,那我们就不需要重复创建。

  • singleTask: 栈内复用模式,当我们创建一个新的Activity的实例的时候,如果当前Activty在任务栈内存在,那我们就不会去重新创建,而是直接将这个实例放置到栈顶,当前Activity上面的所有实例对象都会被移出当前任务栈,进行销毁。

  • singleInstance:此模式有点类似单例模式。当我们创建一个新的Activity的实例的时候,会去创建一个新的任务栈Task,并且这个Task中只有这一个Activity实例。

3.动态设置启动模式

​ 正常情况下,我们可以在Manifest中通过对Activity设置launchMode来指定当前Activity的启动模式,这种设置方式叫做静态设置。而我们在代码中指定Activity的启动模式就为动态设置。如果同时对一个Activity实例设置两种启动模式,那么动态设置的优先级高。

​ 动态设置需要我们在intent进行Activity跳转的时候设置flag标签,例如:

intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK)

​ 常见的Flag有:

  • NEW_TASK
  • SINGLE_TOP
  • CLEAR_TOP
  1. NEW_TASK

    这个flag跟singleInstance有些相似。当我们对Activity设置当前flag的时候,程序会根据当前Activity的affinity进行匹配。如果已经存在与其具有相同affinity属性的task,则直接将Activity压入当前任务栈,如果没有则新建一个task,并将Activity压入新创建的栈内。简单来说就是,根由有没有相同affinity属性的任务栈,有就直接压栈,没有的话就新创建一个。

    这种情况与singleInstance不相同的地方:

    ​ (1) 新的任务栈没有说只可以放一个Activity实例,只是说是否需要创建一个新的Task,而singleInstance模式下新的Task只能存放一个Activity实例。

    ​ (2)在同一个应用下,如果所有的Activity都是默认的affinity,那么当前Flag无效。而singleInstance默认情况下也会创建新的任务栈。

  2. SINGLE_TOP

    当前Flag与静态设置中的singleTop模式等同

  3. CLEAR_TOP

    当我们设置这个flag的时候,如果当前任务栈中已经存在Activity实例,那么我们就将当前Activity实例上面的所有实例都弹出任务栈,需要注意的是:

    (1)如果同时设置Flag_ACTIVITY_SINGLE_TOP,则直接使用栈内对应的Activity

    (2)如果没有设置Flag_ACTIVITY_SINGLE_TOP,则将栈内的对应的Activity销毁,然后重新创建。

    也就是说CLEAR_TOP + SINGLE_TOP相当于我们静态设置的singleTask模式。不同的地方在于他回销毁重新创建。

4.Activity 的生命周期

Activity的生命周期包含:onCreate, onRestart, onStart, onResume, onPause, onStop, onDestory

  • onCreate

    Activity被创建时调用,我们在这个方法中进行初始化操作。

  • onRestart

    Activity由完全不可见变为可见的过程,当Activity由stop方法变为完全不可见之后,如果用户重新返回到当前Activity就会执行这个方法,将会触发这个回调,并且紧接着会调用onStart()来使活动重新可见

  • onStart

    Activity由不可见变为可见,但此时处于后台可见,还不能跟用户进行交互

  • onResume

    可见状态下的Activity由后台进入前台。可以和用户进行交互。

  • onPause

    当用户启动了新的Activity,原来的Activity不再处于前台,也无法与用户进行交互,那么当前Activity就会执行该回调,此方法紧接着会调用onStop方法,但如果用户此时点击返回键重新回到当前Activity就会调用onResume方法让Activity重新回到前台。不允许在onPause方法中执行耗时操作,这样会影响新的Activity的启动速度。

  • onStop

    Activity由可见变为不可见,此方法可以执行一些稍微重量级的操作,需要注意的是,处于onPause和onStop回调的Activity优先级很低,所以在系统内存不足的情况下,就会被杀死,那么再次返回这个Activity的时候,就需要重新执行onCreate方法。

  • onDestory

    Activity即将被销毁,应该在该方法中执行资源的回收和释放工作。

5.Activity 什么时候会发生重建

  • 横竖屏切换,资源重新配置

    可以通过配置android:configChanges属性防止Activity进行重建。

    在API级别为13以下的时候,设置android:configChanges="orientation"

    在API级别为13及13以上的时候,设置android:configChanges="orientation|screenSize"

  • 内存不足,低优先级的Activity会被杀死

    当这种情况的时候,我们可以在onSaveInstanceState存储数据,在onRestoreInstanceState方法中恢复数据,数据可以通过bundle进行存储

关于 onSaveInstanceState 与 onRestoreInstanceState 方法需要注意的一些问题:

  1. onSaveInstanceState的调用时机是在onStop之前,与onPause没有固定的时序关系,而onRestoreInstanceState是在onStart方法之后调用。
  2. 正常情况下的活动销毁并不会调用这两个方法,只有当活动异常销毁并且有机会重现展示的时候才会进行调用,除了资源配置的改变外,activity 因内存不足被销毁也是通过这两个方法保存数据。
  3. 在 onRestoreInstanceState 和 onCreate 都可以进行数据恢复工作,但是根据官方文档建议采用在 onRestoreInstanceState 中去恢复。
  4. 在 onSaveInstanceState 和 onRestoreInstanceState 这两个方法中,系统会默认为我们进行一定的恢复工作,具体地讲,默认实现会为布局中的每个 View 调用相应的 onSaveInstanceState() 方法,让每个视图都能提供有关自身的应保存信息。
  5. onSveInstanceState() 常见的触发场景有:横竖屏切换、按下电源键、按下菜单键、切换到别的 Activity 等;onRestoreInstanceState() 常见的触发场景有:横竖屏切换、切换语言等。

6.Activity中不常用的方法

  • onPostCreate()

    onPostCreate() 方法是指 onCreate() 方法彻底执行完毕的回调。一般我们都没有实现这个方法,它的作用是在代码开始运行之前,调用系统做最后的初始化工作。现在知道的做法是使用 ActionBarDrawerToggle 时在屏幕旋转的时候在 onPostCreate() 中同步下状态。

  • onPostResume()

    onPostResume() 与 onPostCreate() 方法类似,onPostResume() 方法在 onResume() 方法彻底执行完毕的回调。 onCreate() 方法中获取某个 View 的高度和宽度时,返回的值是 0 ,因为这个时候 View 可能还没初始化好,但是在 onPostResume() 中获取就不会有问题,因为 onPostResume() 是在 onResume() 彻底执行完毕的回调。

  • onContentChanged()

    当 Activity 的布局改动时,即 setContentView() 或者 addContentView() 方法执行完毕时就会调用该方法。所以,Activity 中 View 的 findViewById() 方法都可以放到该方法中。

  • onUserInteraction()

    Activity 无论分发按键事件、触摸事件或者轨迹球事件都会调用 Activity#onUserInteraction()。如果想知道用户用某种方式和你正在运行的 activity 交互,可以重写 Activity#onUserInteraction()。所有调用 Activity#onUserLeaveHint() 的回调都会首先回调 Activity#onUserInteraction() 。

    Activity 在分发各种事件的时候会调用该方法,注意:启动另一个 activity ,Activity#onUserInteraction()会被调用两次,一次是 activity 捕获到事件,另一次是调用 Activity#onUserLeaveHint() 之前会调用 Activity#onUserInteraction() 。

    可以用这个方法来监控用户有没有与当前的 Activity 进行交互。

  • onUserLeaveHint()

    当用户的操作使一个 activity 准备进入后台时,此方法会像 activity 的生命周期的一部分被调用。例如,当用户按下 Home 键,Activity#onUserLeaveHint() 将会被调用。但是当来电导致 activity 自动占据前台(系统自动切换),Activity#onUserLeaveHint() 将不会被回调。

你可能感兴趣的:(Activity相关面试基础点)