Activity的本质是一种界面
界面有Acitivity Window Dialog Toast
Activity的生命周期全面分析
典型情况下的生命周期分析
![这里写图片描述](https://img-blog.csdn.net/20170814121206301?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU2t5bGFrZVh1bg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
如上图所示,正常情况下Activity会经历如下生命周期
onCreate:表示活动正在创建,一般可在此做一些初始化工作比如setContentView 初始化所需数据等
onRestart:表示活动正在重新启动.一般在活动从不可见变回可见时候,onrestart就会被重新调用
onStart:表示活动正在被启动,此时活动可见了但还无法跟用户交互
onResume:可进行交互
onPause:表示正在停止,此时可以做存储数据 停止动画等等操作,只有当onPause所有操作完成时,下个方法才会被调用
onDestroy:表示即将被销毁,可以在这里做回收操作以及最终的资源释放
补充说明:
第一次启动活动:onCreate onStart onResume
当打开新的页面或Home,onPause onStop >>如果被打开的活动采用了透明主题则只执行onPause
再次回到页面:onRestart onStart onResume
按下回退:onPause onStop onDestroy
Q:看起来作用差不过,为什么需要三对方法?
A:从不同的角度看待操作:
从是否创建/是否可见/是否前台三个角度看待问题的
Q:从A打开B,谁的onPause会先被调用呢?
A:从源码:在新的页面被打开前,栈顶的A需要先onPause才能启动故:
AonPause BonCreate BonStart BonResume AonStop
异常状态下的生命周期分析
当资源相关的配置发生改变以及系统内存不足的时候,活动可能会被杀死
1.资源相关配置发生改变
例如横竖屏切换会导致活动需要从新加载从而获取到不同分辨率下的drawable
08-14 00:35:50.359 19700-19700/com.junx.artofandroiddeveloping V/meee: AonCreate
08-14 00:35:50.360 19700-19700/com.junx.artofandroiddeveloping V/meee: AonStart
08-14 00:35:50.362 19700-19700/com.junx.artofandroiddeveloping V/meee: AonResume
08-14 00:35:55.943 19700-19700/com.junx.artofandroiddeveloping V/meee: AonPause
//stop之前应该有onSaveInstanceState被调用,但是我的试验下并没有
08-14 00:35:55.945 19700-19700/com.junx.artofandroiddeveloping V/meee: AonStop
08-14 00:35:55.945 19700-19700/com.junx.artofandroiddeveloping V/meee: AonDestroy
08-14 00:35:55.977 19700-19700/com.junx.artofandroiddeveloping V/meee: AonCreate
08-14 00:35:55.978 19700-19700/com.junx.artofandroiddeveloping V/meee: AonStart
08-14 00:35:55.978 19700-19700/com.junx.artofandroiddeveloping V/meee: AonRestoreInstanceState
08-14 00:35:55.980 19700-19700/com.junx.artofandroiddeveloping V/meee: AonResume
保存操作:
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState)
outState.putString("A","test")
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState)
Log.v("meee","A"+"onRestoreInstanceState")
String a = savedInstanceState.getString("A")
Log.v("meee","保存的数据为"+a)
}
当系统配置发生改变后,可以通过设置使其不发生重新创建
在配置文件中指定活动的android:configChanges属性
<activity android:name=".LifeOfActivity"
android:configChanges="orientation">
常用设置:
android:configChanges="orientation" 方向
android:configChanges="keyboardHidden" 键盘的可访问性,如用户使用了外插键盘
android:configChanges="locale" 一般指切换了语言
资源内存不足导致低优先级的活动被杀死
优先级:
前台活动:正在与用户交互的活动
可见但不是前台:弹出了一个对话框
后台:执行了onStop
Activity的启动模式
standard:标准模式,每次启动活动都会重新创建一个实例,不管这个实例是否存在.
ps:用application的Context启动standard模式的活动会报错
这是因为标准模式的活动默认会进入启动它的任务栈中,而application没有任务栈
pps后:某个版本修复这个了错误
singleTop:栈顶复用模式.在这种模式下,如果新的activity已经位于栈顶,那么不会创建,同时它的onNewIntent()会被回调,通过该方法我们可以取出当前请求的信息.
singleTask:栈内复用模式.只要栈内有相同的实例,那么不会创建新的活动,只调用onNewIntent()
如果被启动的活动不是栈顶,那么会销毁该活动上的所有任务使其在栈顶
singleInstance:单实例模式
静态配置启动模式:
<activity android:name=".BActivity"
android:launchMode="standard">
动态配置启动模式:
Intent intent = new Intent(getApplicationContext(),BActivity.class)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
Activity的Flags
以下是一些常用的Flag
FLAG_ACTIVITY_NEW_TASK:与singleTask相同
FLAG_ACTIVITY_SINGLE_TOP:同singletop
FLAG_ACTIVITY_CLEAR_TOP:同singTask
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:等同于在xml中配置活动的属性android:excludeFromRecents="true".该活动不会出现在历史Acitivity的列表中
IntentFilter的匹配规则
我们都知道,启动活动的方法分为显示启动和隐式启动,而这的区别在于显式启动需要明确的只i的那个对象的组件信息,包括包名和类型
隐式启动:
需要Intent能够匹配目标组件中的IntentFilter中的所设置的过滤信息;
IntentFilter中的过滤信息有三种
action的匹配规则:
action是一个字符串,action的匹配规则是指Intent中的action必须能和过滤规则中的action匹配;
一个intentFilter中可以有多个action,那么只要能匹配一个action即视作匹配成功 ;
category的匹配规则:
category是一个字符串,与action不同;
一个intentFilter中可以有多个category,那么每个category都要匹配上才能算成功;
只要存在action必须存在一个默认的category:
<category android:name="android.intent.category.DEFAULT"/>,因为系统在调用startActivity startAcitivityForResult的时候会默认的加上默认的category,而只要存在category必须有匹配对象
data的匹配规则:
<data
android:port="string"
android:host="string"
android:mimeType="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:scheme="string"
/>
data由两部分组成:
mimeType:媒体类型如image/jpeg audio/mpegg4-generic vides/*等等
URI:<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
如:content:com.example.project:200/folder/subfolder/etc
Scheme:URL模式,比如http file content,如没有指定则真个参数无效
Host:uri的主机名,没有指定也是无效
Port:uri的端口号
Path pathPattern pathPrefix:这三个参数表述路径信息,path表示完整的路径,pathpattern也表示完整的路径,但是可以包含通配符号,但注意由于正则表达式的规范如果想表示真正的字符串 "*">>"\\*" "\">"\\\\"
pathPrefix表示路径的前缀信息
Demo
<intent-filter>
<action android:name="com.ryg.a.a"/>
<action android:name="com.ryg.a.b"/>
<category android:name="com.ryg.b.a"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/*"
android:scheme="http"/>
</intent-filter>
Intent intent = new Intent();
intent.setAction("com.ryg.a.a");
intent.addCategory("com.ryg.b.a");
intent.setDataAndType(Uri.parse("http://abc"),image/png);
startActivity(intent);
查看是否有与Intent匹配的activity的方法,提升代码健壮性
PackageManager.resolveActivity
Intent.resolveActivity
若没有则会返回null
demo:
ComponentName componentName = intent.resolveActivity(getPackageManager())
ResolveInfo componentName = getPackageManager().resolveActivity(intent, MATCH_DEFAULT_ONLY)
声明启动activity
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
二者缺一不可