Android开发艺术探索学习笔记(二)
android,艺术探索,学习笔记2016-08-03
学习章节:
第一章 Activity的生命周期和启动模式
学习时间:
2016.8.3
学习内容:
1.2 Activity的启动模式
任务栈:任务栈Task:一种以栈的形式来存放Activity实例的容器,原则是“后进先出”,主要有两个操作:压栈和出栈。其中存放的Activity是不支持重新排序的,只能根据压栈和出栈操作更改Activity的顺序。是为实现一个功能而负责管理所有用到的Activity实例的栈。默认情况下,所有Activity所需的任务栈名字为应用的包名。
启动一个Application的时候,系统会为它默认创建一个对应的Task,用来放置根Activity。默认情况下,启动Activity会放在同一个Task中,新启动的Activity会被压入启动它的那个Activity的栈中,并且显示新启动的Activity。当用户按下回退键时,这个Activity就会被弹出栈;当按下Home键回到桌面,再启动另一个应用,这时候之前那个Task就被移到后台,成为后台任务栈,而刚启动的那个Task就被调到前台,成为前台任务栈,Android系统显示的就是前台任务栈中的Top实例Activity。
启动模式: 通过设置启动模式来修改系统的默认行为
standard:标准模式,可以不用写配置,这也是系统的默认模式。每次启动一个Activity都会创建一个新的实例,不管这个实例是否已经存在。
应用场景:绝大多数Activity。
singleTop:栈顶复用模式,在这中模式下,如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它的onNextIntent方法会被回调,通过此方法的参数我们可以取出当前请求的信息。需要注意的是,这个Activity的onCreate和onStart不会被系统调用,因为它并没有发生改变。
应用场景:假设目前栈内的情况为ABC,其中ABC为三个Activity,A位于栈底,C位于 栈顶。这个时候再次启动C,如果C的启动模式为singleTop,那么栈内的情况依然为ABC;如果C的启动模式为standard,那么由于C被创建,导致栈内的情况就变为ABCC。
singleTask:栈内复用模式, activity只会在任务栈里面存在一个实例。如果要激活的activity,在任务栈里面已经存在,就不会创建新的activity,而是复用这个已经存在的activity,调用 onNewIntent() 方法,并且清空这个activity任务栈上面所有的activity。
应用场景:大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。
测试例子:首先从主界面A跳转到第二个界面B,再从第二个界面B跳转到第三个界面C,最后从第三个界面C跳转到主界面A。
main.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this, SecondActivity.class));
}
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
second.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(getApplicationContext(), ThirdActivity.class));
}
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
third.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(getApplicationContext(), MainActivity.class));
}
});
设置主界面A的启动模式为,其他两个是默认启动模式
android:launchMode="singleTask"
我们监听一下最后从第三个界面C跳转到主界面A发生了什么:
第二个界面B首先执行了onDestroy,然后第三个界面C也执行了onDestroy,也就是说两个Activity的实例都被销毁了,是不是这样呢?我们这时候在主界面按返回键,看看发生了什么:
果然,主界面A实例销毁,直接退出了应用,与预期效果一致。
singleInstance:单一实例模式,整个手机操作系统里面只有一个实例存在。不同的应用去打开这个activity 共享公用的同一个activity。他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。
应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。建议谨慎使用。
1.3 Activity的Flags
系统提供了两种方式来设置一个Activity的启动模式,除了在AndroidManifest文件中设置以外,还可以通过Intent的Flag来设置一个Activity的启动模式,下面我们在简单介绍下一些Flag。
FLAG_ACTIVITY_NEW_TASK
使用一个新的Task来启动一个Activity,但启动的每个Activity都讲在一个新的Task中。该Flag通常使用在从Service中启动Activity的场景,由于Service中并不存在Activity栈,所以使用该Flag来创建一个新的Activity栈,并创建新的Activity实例。
FLAG_ACTIVITY_SINGLE_TOP
使用singletop模式启动一个Activity,与指定android:launchMode=“singleTop”效果相同。
FLAG_ACTIVITY_CLEAR_TOP
使用SingleTask模式来启动一个Activity,与指定android:launchMode=“singleTask”效果相同。
FLAG_ACTIVITY_NO_HISTORY
Activity使用这种模式启动Activity,当该Activity启动其他Activity后,该Activity就消失了,不会保留在Activity栈中。
测试例子:
还是上面一样的场景,这次我们不在配置文件设置,将从第三个界面C跳转到主界面A的代码设置如下:
third = (Button) findViewById(R.id.third_btn);
third.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setClass(ThirdActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
看看发生了什么:
然后按下返回键:
与预期效果一致,完美
1.4 IntentFilter的匹配原则
只有一个Intent同时匹配action类别,category类别,date类别才算完全匹配,只有完全匹配才能成功启动目标Activity。一个Activity中可以有多个intent-filter,一个Intent只要能匹配任何一组intent-filter即可成功启动对应的Activity。
action的匹配规则:
action的匹配要求Intent中的action存在且必须和过滤规则中的其中一个action相同,action区分大小写,大小写不同字符串相同的action会匹配失败。
category的匹配规则:
Intent如果含有category,那么所有的category都必须和过滤规则中的其中一个category相同,如果没有category依旧可以匹配成功。
data的匹配规则:
与action类似,如果过滤规则中定义了data,那么Intent中必须也要定义可匹配的data。