一、Activity生命周期分析
- Activity在onStart()的时候还在后台,onResume()的时候才显示到前台。
- 在新Activity启动之前,栈顶的Acticity需要先onPause()后,才执行新Activity的onCreate(),因此不能在onPause()中执行耗时的操作,尽量在onStop中做耗时的操作。
- onStop()不能确定具体执行时间
异常情况下的生命周期分析:
- 1、资源相关的系统配置发生改变导致Activity被杀死并重新创建
- 保存:销毁时调用onSaveInstanceState()
- 保存的是Bundle对象
- 调用时机是在onStop之前,与onPause没有既定的时序关系
- 只有在异常关闭才会调用,比如突然横屏,正常如调用finish()的时候不会调用
- 取出:重新创建后调用onRestoreInstanceState()
- 取出onSaveInstanceState()保存的Bundle对象,传递给onRestoreInstanceState()和onCreate()。
- onRestoreInstanceState()在调用时机在onStart()之后
- 两个方法二选一进行恢复,官方建议onRestoreInstanceState()。区别是onRestoreInstanceState()中的Bundle对象savedInstanceState一定是有值的,而onCreate()中的为null。
- 保存流程
- 委托思想:上层委托下层、父容器委托子元素
- Activity首先调用onSaveInstance,然后委托Window保存数据,Window委托它上面的顶级容器(ViewGroup,一般是DecorView),然后再一一通知子元素保存数据。
- 保存:销毁时调用onSaveInstanceState()
2、资源内存不足导致低优先级的Activity被杀死
- Activity优先级从高到低依次为:
- 前台Activity,优先级最高
- 可见但非前台Activity
- 后台Activity,如执行了onStop()的activity,优先级最低
- 因此后台工作不适合放在Activity中,最好放在Service中并保证进程有一定的优先级。
- 给Activity指定configChange属性可以避免在某项内容发生改变的时候系统重新创建Activity,而是调用Activity的onConfigurationChanged()方法
//避免Activity在屏幕旋转的时候重新创建 android:configChanges="orientation"
- Activity优先级从高到低依次为:
二、Activity的启动模式
①可通过AndroidManifest指定
②可通过在Intent中设置标志位指定(优先级较第一种高)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1、Activity的LaunchMode
- (1)standard:标准模式
- 典型的多实例实现
- 新启动的Activity会默认进入启动他的Activity所属的任务栈
- 只有Activity类型的Context才有任务栈。当遇到ApplicationContext或ServiceContext启动Activity时,使用FLAG_ACTIVITY_NEW_TASK标记位创建一个新的任务栈,该Activity实际是以singleTask模式启动的
- (2)singleTop:栈顶复用模式
- 如果新Activity已经位于栈顶时,不会创建新的实例,回调onNewIntent()方法。
- (3)singleTask:栈内复用模式
- 是一种单实例模式
- 当Activity实例已存在时,同样不会创建新实例,将该实例顶到栈顶,将原先在上方的Activity全部出栈(后进先出原则),并回调onNewIntent()方法。
- 首先寻找是否存在待启动Activity想要的任务栈,有的话直接入栈,没有的话就创建一个新的并入栈。(即标准模式中的例子)
- TaskAffinity标识所需任务栈的名字,默认情况下为应用包名,其值为字符串,中间必须有包名分隔符“.”。主要与allowTaskReparenting属性一起使用,如果该属性为true,则Activity可跨进程进入其他栈。
- 然后看栈中是否有没有相同的实例。
- 首先寻找是否存在待启动Activity想要的任务栈,有的话直接入栈,没有的话就创建一个新的并入栈。(即标准模式中的例子)
- 默认具有ClearTop属性
- (4)singleInstan:单实例模式
- 一种加强的singleTask模式,具有singleTask模式所有特性
- 具有此种模式的Activity只能单独的位于一个任务栈中,启动该栈中Activity时,会将整个任务栈提前
2、Activity的Flags
- FLAG_ACTIVITY_NEW_TASK
- 具有此标记位的Activity启动模式为singleTask
- FLAG_ACTIVITY_SINGLE_TOP
- 具有此标记位的Activity启动模式为singleTop
- FLAG_ACTIVITY_CLEAR_TOP
- 具有此标记位的Activity,在启动时会将同一个栈中位于它上面的Activity全部出栈
- standard模式启动的Activity具有此标记时,如果该Activity在栈中已存在,会将它连同它之上的Activty全部出栈,然后创建新的实例
- singleTask启动模式默认具有此标记位的效果
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- 具有这个标记位的Activity不会出现在历史Activity列表中,等同于指定Activity属性Android:excludeFromRecents=”true”
三、IntentFilter的匹配规则
启动Activity的隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息。只有**同时匹配**action、category、data类别,才能成功启动Activity。
- 一个Activity中可以有多个IntentFilter,只要匹配一个就能启动对应的Activity。
1、aciton匹配规则
action是一个字符串,区分大小写。匹配是指字符串值完全一样
- 可以设置多个,至少有一个、只要有一个相同即匹配
- 如果没有指定action,则匹配失败
2、category匹配规则
category也是一个字符串。
- 默认匹配成功。系统调用startActivity或startActivityForResult的时候,默认为Intent加上android.intent.category.DEFAULT
- 每一个指定的category都必须相同才匹配
3、Data的匹配规则
Data由两部分组成
- mimeType:媒体类型
URI:默认值为content和file
- Scheme:URI的模式,必须指定
- Host:URI的主机名,必须指定
- Port:URI的端口号
- 路径信息
- path:完整路径信息
- pathPattern:完整路径信息,可包含通配符“*”
- pathPrefix:路径前缀信息
//格式 <scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>] //示例 http://www.baidu.com:80/search/info
- 匹配规则:至少有一个,只要有一个相同就匹配
- 使用 intent.setDataAndType() 方法为Intent指定完整的data
检测Activity是否能匹配隐式Intent
- PackageManager或Intent的resolveActivity(Intent intent, int flags);
- 返回最佳匹配的信息,找不到匹配则返回null
- PackageManager的queryIntentActivities(Intent intent, int flags);
- 返回所有成功匹配的Activity信息,找不到匹配则返回null
- flag标记位使用MATCH_DEFAULT_ONLY:匹配所有category中带有default的Activity,即能够接收隐式Intent的Activity,只要不返回null,确保startActivity成功。
标志入口Activity
<action android:name="android.intent.action.MAIN" />
<category adnroid:name="android.intent.category.LAUNCHER" />