Android基础之Activity全解析

概念

Android四大应用组件之一,与用户交互的接口,界面的载体。java

生命周期

  • onCreate(),生命周期第一个方法,表示Activity正在建立过程当中。通常作一些初始化工做,setContentView()加载界面布局等。
  • onStart(),表示Activity正在启动过程当中,Activity可见但不可与用户交互。
  • onReStart(),表示Activity正在从新启动过程当中,通常Activity由不可见到可见过程当中会回调此方法。
  • onResume(),Activity显示在前台并可与用户交互。
  • onPause(),表示Activity正在中止,可作中止动画,存储数据操做,不能作耗时操做。
  • onStop(),表示Activity即将中止,可作轻量级回收工做。
  • onDestory(),表示Activity即将销毁,生命周期最后一个方法。

从整个生命周期来讲,onCreate与onDestory是配对的,标志销毁与建立,真个生命周期只会回调一次。onStart与onStop是配对的,标志Activity是否可见。onResume与onPause是配对的,标志是否处于前台可与用户交互。android

onPause不能作太耗时的操做,不然会影响新的Activity的显示app

  • 首次启动Activity,系统会先回调onCreate方法而后调用onStart,onResume,Activity进入运行状态。
  • 当前Activity被其余Activity覆盖其上或被锁屏(能够理解为没有彻底遮挡界面),系统会调用onPause方法,暂停当前Activity的执行。
  • 当前Activity由被覆盖状态回到前台或解锁屏,系统会调用onResume方法,再次进入运行状态。
  • 当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台,系统会先调用onPause方法,而后调用onStop方法,进入停滞状态。(若是新Activity采用透明主题,当前Activity不会回调onStop方法)
  • 用户后退回到此Activity,系统会先调用onRestart方法,而后调用onStart方法,最后调用onResume方法,再次进入运行状态。
  • 用户退出当前Activity,系统先调用onPause方法,而后调用onStop方法,最后调用onDestory方法,结束当前Activity。

A Activity启动B Activity的生命周期状况: A执行onCreate,onStart,onResume到可交互状态,此时启动B Activity,首先将执行A Activity的onpause暂停A Activity执行,而后执行B Activity的onCreate,onStart,onResume到可交互状态,而后再执行A Activity的onStop方法(若是B Activity未彻底遮挡A Activity, 将不会回调A Activity的onStop方法),若是启动B Activity时失败,A Activity将从onPause状态回到onResume执行。布局

home键/锁屏生命周期状况: onPause -> onStop动画

back键/清除recent生命周期状况: onPause -> onStop -> onDestoryui

异常状况的销毁与恢复

当系统“未经用户许可”销毁activity时,会回调onSaveInstanceState方法保存数据,让界面能够恢复。onSaveInstanceState方法何时会执行?google

  1. 当用户按下HOME键时。系统不知道你按下HOME后要运行多少其余的程序,天然也不知道activity是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。
  2. 长按HOME键,选择运行其余的程序时。
  3. 按下电源按键(关闭屏幕显示)时。
  4. 从activity A中启动一个新的activity时。
  5. 屏幕方向切换时,例如从竖屏切换到横屏时。

onCreate()里也有Bundle参数,能够用来恢复数据,它和onRestoreInstanceState有什么区别?翻译

由于onSaveInstanceState 不必定会被调用,因此onCreate()里的Bundle参数可能为空,若是使用onCreate()来恢复数据,必定要作非空判断。而onRestoreInstanceState的Bundle参数必定不会是空值,由于它只有在上次activity被回收了才会调用。并且onRestoreInstanceState是在onStart()以后被调用的。有时候咱们须要onCreate()中作的一些初始化完成以后再恢复数据,用onRestoreInstanceState会比较方便。onSaveInstanceState调用时机在onStop()前,onRestoreInstanceState的调用时机实在onStart()以后。cdn

注意:xml

onSaveInstanceState方法和onRestoreInstanceState方法“不必定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而若是仅仅是停留在有这种可能性的状况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,而后用户紧接着又返回到activity A,这种状况下activity A通常不会由于内存的缘由被系统销毁,故activity A的onRestoreInstanceState方法不会被执行。

onSaveInstanceState和onRestoreInstanceState方法中,系统自动作了一系列恢复动做,系统会默认保存当前Activity视图结构,并在Activity重启后恢复这些数据。Activity被意外终止时,首先会回调onSaveInstanceState保存数据,而后委托Window -> DecorView -> View一层层保存数据。与Activity同样,每一个View都有onSaveInstanceState和onRestoreInstanceState方法。

启动模式

任务栈(task stack)

为了记录用户开启了那些activity,记录这些activity开启的前后顺序,google引入任务栈(task stack)概念,以栈的结构(先进后出)将依次打开的activity记录保存在task stack中。

启动模式

Standard

默认Standard模式,假设没有为Activity设置启动模式的话,默认是标准模式。即每次启动一个Activity都会又一次建立一个新的实例入栈,不管这个实例是否存在。Standard模式的Activity默认会进入启动它的Activity所属的任务栈(启动它的Activity为SingleInstance的状况除外)。

SingleTop

当建立的Activity已经处于栈顶时,此时会直接复用栈顶的Activity,不会再建立新的Activity。若需要建立的Activity不处于栈顶,此时会又一次建立一个新的Activity入栈,同Standard模式同样。 栈顶的Activity被直接复用时,onCreate、onStart不会被系统调用,而是回调onNewIntent方法(Activity被正常建立时不会回调此方法),而后再执行onResume。(实际是onPause -> onNewIntent -> onResume)

SingleTask

栈内复用模式,若需要建立的Activity已经处于栈中时,此时不会建立新的Activity,而是将存在栈中的Activity上面的其余Activity全部销毁,使它成为栈顶。 同SingleTop模式中同样,onCreate、onStart不会被系统调用,仅仅回调Activity中的onNewIntent方法。

好比启动Activity A,先找其对应的任务栈,若是不存在,则先新建任务栈,在建立Activity A放到任务栈中。若是存在,则判断栈中是否存在Activity A的实例,若是存在则把Activity A调到栈顶,而后调用其onNewIntent方法。若是不存在Activity A的实例,则新建Activity A放到任务栈中。

SingleTask会致使它之上的栈内全部Activity出栈

SingleInstance

具备此模式的Activity仅仅能单独位于一个任务栈中

taskAffinity

taskAffinity,能够翻译为任务相关性。这个参数标识了一个 Activity 所须要的任务栈的名字,默认状况下,全部 Activity 所需的任务栈的名字为应用的包名,当 Activity 设置了 taskAffinity 属性,那么这个 Activity 在被建立时就会运行在和 taskAffinity 名字相同的任务栈中,若是没有,则新建 taskAffinity 指定的任务栈,并将 Activity 放入该栈中。另外,taskAffinity 属性主要和singleTask或者allowTaskReparenting属性配对使用,在其余状况下没有意义。

  • taskAffinity对Standard与SingleTop,SingleInstance没有影响
  • taskAffinity对SingleTask的影响: 以A启动B来讲 当A和B的taskAffinity相同时:第一次建立B的实例时,并不会启动新的task,而是直接将B添加到A所在的task;当B的实例已经存在时,将B所在task中位于B之上的所有Activity都移除,B就成为栈顶元素,实现跳转到B的功能。 当A和B的taskAffinity不一样时:第一次建立B的实例时,会启动新的task,而后将B添加到新建的task中;当B的实例引进存在,将B所在task中位于B之上的所有Activity都移除,B就成为栈顶元素(也是root Activity),实现跳转到B的功能。

使用场景

  • Standard 普通状况下使用
  • SingleTop 适用于同类型的Activity,例如通知栏消息接收启动的Activity
  • SingleTask 主界面
  • SingleInstance 适合公开成通用功能的Activity,例如拨号,闹钟界面等

Activity Flags

  1. FLAG_ACTIVITY_NEW_TASK 做用是为Activity指定 “SingleTask”启动模式。跟在AndroidMainfest.xml指定效果一样。

注意: FLAG_ACTIVITY_NEW_TASK与FLAG_ACTIVITY_CLEAN_TOP才具有AndroidMainfest.xml指定SingleTask一样效果

  1. FLAG_ACTIVITY_SINGLE_TOP 做用是为Activity指定 “SingleTop”启动模式,跟在AndroidMainfest.xml指定效果一样。

  2. FLAG_ACTIVITY_CLEAN_TOP 具备此标记位的Activity,启动时会将与该Activity在同一任务栈的其余Activity出栈。通常与SingleTask启动模式一块儿出现。它会完毕SingleTask的做用。但事实上SingleTask启动模式默认具备此标记位的做用

  3. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 具备此标记位的Activity不会出现在历史Activity的列表中,使用场景:当某些状况下咱们不但愿用户经过历史列表回到Activity时,此标记位便体现了它的效果。它等同于在xml中指定Activity的属性:android:excludeFromRecents="trure"

相关

  1. Activity因系统内存不足被Kill或是由于Crash闪退的异常退出怎么保存数据? Activity被销毁了之后调用了onSaveInstanceState来保存数据,这个只会在Activity即将销毁而且有机会从新显示的状况下才会去调用onSaveInstanceState,与之配对的是在onRestoreInstanceState里恢复数据。

  2. 资源不足时Activity的杀死顺序

    • 前台Activity,正在和用户交互的Activity,优先级最高
    • 可见但非前台Activity,好比Activity中弹出了一个对话框,致使Activity可见可是位于后台没法和用户直接交互。
    • 后台Activity,已经被暂停的Activity,好比执行了onStop,优先级最低
  3. 横竖屏切换时候Activity的生命周期 跟Manifest配置有关

    • 不设置Activity的android:configChanges时,切屏会从新调用各个生命周期默认首先销毁当前activity,而后从新建立
    • 设置Activity的android:configChanges="orientation|screenSize"时,切屏不会从新调用各个生命周期,只会执onConfigurationChanged方法
  4. 启动其余应用Activity时,报java.lang.SecurityException: Permission Denial,由于在其余应用StartActivity时,有去检验permission。

知足如下条件,能够成功startActivity,不会出现permission denial:

  • 同一个application下
  • Uid相同
  • permission匹配
  • 目标Activity的属性Android:exported=”true”
  • 目标Activity具备相应的IntentFilter,存在Action动做或其余过滤器而且没有设置exported=false
  • 启动者的Pid是一个System Server的Pid
  • 启动者的Uid是一个System Uid(android.system.uid=1000)
相关文章
相关标签/搜索