开发艺术探索之Activity

接下来的几天学习任老师的《Android开发艺术探索》,这里做相关的笔记(参考:文章)(同样,作为学习书籍,文章定义为转载)

  • 生命周期全面分析
    • 典型情况下的声明周期
    • 异常情况下的生命周期(两种情况)
  • 四种启动模式
    • 启动方式1:LaunchMode
    • 启动方式2:Flags(不常用)
  • IntentFilter匹配规则

生命周期全面分析

典型情况下的生命周期

生命周期的各阶段

完整生命周期 Activity在onCreate()和onDestroy()之间所经历的。
在onCreate()中完成各初始化操作,在onDestroy()中释放资源。
可见生命周期 Activity在onStart()和onStop()之间所经历的。
活动对于用户是可见的,但仍无法与用户进行交互。
前台生命周期 Activity在onResume()和onPause()之间所经历的。
活动可见且可交互。

正常情况下,Activity会经历以下生命周期

生命周期 状态 任务 备注
onCreate Activity 正在创建 做初始化工作,如setContentView界面资源、初始化数据 此方法的传参Bundle为该Activity上次被异常情况销毁时保存的状态信息
onStart Activity 正在启动 (null) 这时Activity 可见但不在前台,无法和用户交互。
onResume Activity 获得焦点 (null) 此时Activity 可见且在前台并开始活动
onPause Activity 正在停止 可做 数据存储、停止动画等操作 Activity切换时,旧Activity的onPause会先执行,然后才会启动新的Activity
onStop Activity 即将停止 可做稍微重量级回收工作,如取消网络连接、注销广播接收器等 新Activity是透明主题或是dialoge时,旧Activity都不会走onStop
onDestory Activity 即将销毁 回收工作、资源释放 (null)
onRestart Activity 重新启动 (null) Activity由后台切换到前台,由不可见到可见

常见情况的生命周期切换过程

动作 切换过程
启动Activity1

onCreate()-->onStart()-->onResume()

在Activity1打开一个新Activity2

Activity1的onPause() -->Activity2的onCreate()-->onStart()-->onResume()-->Activity1的onStop()

Activity2返回到Activity1

Activity2的onPause()-->Activity1的onRestart()-->onStart()-->onResume()-->Activity2的onStop()-->onDestory()

Activity1上弹出对话框Activity2

Activity1的onPause()-->Activity2的onCreate()-->onStart()-->onResume()

关闭屏幕/按Home键

Activity2的onPause()-->onStop()-->Activity1的onStop()

点亮屏幕/回到前台

Activity2的onRestart()-->onStart()-->Activity1的onRestart()-->onStart()-->Activity2的onResume()

关闭对话框Activity2

Activity2的onPause()-->Activity1的onResume()-->Activity2的onStop()-->onDestroy()

异常情况下的生命周期(两种情况)

情况一:由于资源相关配置发生改变,导致Activity被杀死和重新创建

例如屏幕发生旋转:当竖屏切换到横屏时,会先调用onSaveInstanceState来保存切换时的数据,接着销毁当前的Activity,然后重新创建一个Activity,再调用onRestoreInstanceState恢复数据。(文本框数据、listView位置等相关信息系统会自动帮我们恢复,我们也可以重写)(onSaveInstanceState方法只会在Activity异常终止的情况下调用

  • 相应的生命周期为onSaveInstanceState(此方法也可能在onPause后调用)-->onPause-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume
  • 可通过onRestoreInstanceState(Bundle savedInstanceState)和onCreate((Bundle savedInstanceState)来判断Activity是否被重建,并取出数据进行恢复。但需要注意的是,在onCreate取出数据时一定要先判断savedInstanceState是否为空。(谷歌推荐使用onRestoreInstanceState进行数据恢复。)

  • onSaveInstanceState与onPause的区别:前者适用于对临时性状态的保存,而后者适用于对数据的持久化保存。)
  • 为了避免由于配置改变导致Activity重建,可在AndroidManifest.xml中对应的Activity中设置android:configChanges="orientation|screenSize"。此时再次旋转屏幕时,该Activity不会被系统杀死和重建,只会调用onConfigurationChanged。因此,当配置程序需要响应配置改变,指定configChanges属性,重写onConfigurationChanged方法即可。

情况二:由于系统资源不足,导致优先级低的Activity被回收

Activity优先级排序:前台可见Activity>前台可见不可交互Activity(前台的Activity弹出了Dialog)>后台Activity(用户按下Home键、切换到其他应用)

当系统内存不足时,会按照Activity优先级从低到高去杀死目标Activity所在的进程,并通过onSaveInstanceState和onRestoreInstanceState来存储和恢复数据。如果一个进程没有四大组件在执行,那么这个进程将很快被系统杀死。

四种启动模式

设置Activity启动模式的方法(两种)

  • 在AndroidManifest.xml中给对应的Activity设定属性:  android:launchMode="standard|singleInstance|single Task|singleTop"。
  • 通过标记位设定,方法是intent.addFlags(Intent.xxx)

优先级上,第二种优先级高于第一种,同时存在时,以第二种为准。(第一种无法直接为Activity设定FLAG_ACTIVITY_SINGLE_TOP,第二种无法为Activity指定singleInstance模式)

Activity的四种LaunchMode

英文名称 名称 含义 备注 使用实例
standard 标准模式、默认模式 每次启动一个Activity就会创建一个新的实例。 使用ApplicationContext去启动standard模式Activity就会报错。因为standard模式的Activity会默认进入启动它所属的任务栈,但是由于非Activity的Context没有所谓的任务栈

情况:A-->A-->A:

返回时:A-->A-->A-->退出

singleTop 栈顶复用模式 如果新Activity已经位于任务栈的栈顶,就不会重新创建,并回调onNewIntent(intent)方法。  

情况:A-->B-->A

返回时:A-->B-->A-->退出

singleTask 栈内复用模式 只要该Activity在一个任务栈中存在,都不会重新创建,并回调onNewIntent(intent)方法。如果不存在,系统会先寻找是否存在需要的栈,如果不存在该栈,就创建一个任务栈,并把该Activity放进去;如果存在,就会创建到已经存在的栈中。 (若所需要的栈内存在实例,则会调用该实例的onNewIintent,并把该实例上面的Activity全部出栈)

情况1:A-->B-->A

返回时:A-->退出

情况2:A-->B-->B

返回时:B-->A-->退出

singleInstance 单实例模式  (可以理解为加强版的singleTask)具有此模式的Activity只能单独位于一个任务栈中,且此任务栈中只有唯一一个实例。    

常用的可设定Activity启动模式的标记位(不常用)

  • FLAG_ACTIVITY_SINGLE_TOP:对应singleTop启动模式。
  • FLAG_ACTIVITY_NEW_TASK :对应singleTask模式。
  • FLAG_ACTIVITY_CLEAR_TOP:当相应的Activity启动时,同一个任务栈中所有位于它上面的Activity都要出栈。(一般配合FLAG_ACTIVITY_NEW_TASK使用。)
  • FLAG_ACTIVITY_FROM_RECENTS:具有这个标记的Activity不会出现在历史Activity的列表中(当某些情况下我们不希望用户通过历史列表回到我们的Activity'的时候使用这个标记比较有用。它等同于在xml指定Activity的属性:android:excludeFromRecents=“true”)

IntentFilter匹配规则

因为启动Activity可以显示调用和隐式调用,显示调用只需要明确指定被启动对象的组建信息(包名和类名),隐式调用需要Intetn能够匹配目标组件的IntenFilter中所设置的过滤信息。

  • 一个intent只有同时匹配某个Activity的intent-filter中的action、category、data才算完全匹配,才能启动该Activity。
  •  一个Activity可以有多个 intent-filter,一个 intent只要成功匹配任意一组 intent-filter,就可以启动该Activity。
  • 可以用PackageManager的resolveActivity方法或者Intent的resolveActivity方法判断是否有Activity匹配该隐式Intent。

action匹配规则:

  • 要求intent中的action 存在且必须和intent-filter中的其中一个 action相同。
  • 区分大小写。

 category匹配规则:

  • intent中的category可以不存在,这是因为此时系统给该Activity 默认加上了< category android:name="android.intent.category.DEAFAULT" />属性值。
  • 除上述情况外,有其他category,则要求intent中的category和intent-filter中的所有category 相同。

data匹配规则:

  • 如果intent-filter中有定义data,那么Intent中也必须也要定义data。
  • data主要由mimeType(媒体类型)和URI组成。在匹配时通过intent.setDataAndType(Uri data, String type)方法对date进行设置。
  • 要求和action相似:如果没有指定URI,默认值为content和file; 有多组data规则时,匹配其中一组即可。

猜你喜欢

转载自blog.csdn.net/easy_purple/article/details/84678255