作者:Dimon
- 微博:@Dimon-喰
- GitHub:@Dimon94
- LOFTER:@Dimon、
复习一点:启动
Activity
时,系统会创造实例并把他们放入任务栈里,而任务栈是一种“后进先出”的栈结构。
Activity
的四种启动模式:
standard:标准模式、默认模式。每次启动一个Activity
都会重新创建一个新的实例,不管这个实例是否已经存在。在这种模式下,某个Activity
启动了一号Activity
,那么一号Activity
就运行在启动它的那个Activity
所在的栈中。
singleTop:栈顶复用模式。如果新的Activity
已经位于任务栈的栈顶,那么此Activity
就不会被重新创建,同时它的onNewIntent
方法会被回调,并且可以根据此方法的参数获得当前请求的信息。
singleTask:栈内复用模式。在这种单实例模式下,只要Activity
在一个栈中存在,那么多次启动此Activity
都不会重新创建实例,系统也会调用其onNewIntent
。
Activity
只能单独地位于一个任务栈中。注:在任何跳转的时候,首先调用本
Activity
的onPause
,然后跳转。如果被跳转的activity
由于启动方式而没创建新的实例,则会先调用onNewIntent
,然后按照正常的生命周期调用。
如:
首先要说明:任务栈分为前台任务栈和后台任务栈,后台任务栈中的
Activity
位于暂停状态。
当在前台任务栈AB启动Activity D,而D正好是后台任务栈CD的栈顶。现在假设后台任务栈里的Activity的启动模式是singleTask
,请求启动D,那么整个后台任务栈都会被切换到前台,直接占据前台任务栈的栈顶,即ABCD。如果之前请求启动的是C,那么就会变成ABC。
singleTask
模式的Activity
切换到栈顶会导致在它之上的栈内的Activity
出栈。
TaskAffinity
:任务相关性。标识一个Activity
所需要的任务栈的名字。
adnroid:taskAffinity="com.dimon.task1"
默认情况下Activity
所需要的任务栈的名字为应用的包名。
AndroidMenifest
为Activity
指定启动模式。<activity android:name="com.dimon.SecondActivity" android:configChanges="screenLayout" adnroid:taskAffinity="com.dimon.task1" android:launchMode="singleTask" android:label="@string/app_name"/>
Intent
中设置标志位来为Activity
指定启动模式。Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
FLAG_ACTIVITY_NEW_TASK
标识,而第二种无法指定singleTask
模式。FLAG_ACTIVITY_NEW_TASK
这个标记位的作用是为Activity
指定“singleTask
”启动模式,其效果和在XML中指定该启动模式相同。
FLAG_ACTIVITY_SINGLE_TOP
这个标记位的作用是为Activity
指定“singleTop
”启动模式,其效果和在XML中指定该启动模式相同。
FLAG_ACTIVITY_CLEAR_TOP
具有此标记位的Activity
,当它启动时,在同一个任务栈中所有位于他上面的Activity
都要出栈。singleTask
默认就具有这个标记位的效果。如果被启动的Activity
采用了standard
启动模式,那么它连通它之上的Activity
都要出栈,系统会创建新的Activity
实例并放入栈顶。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有这个标记的Activity
不会出现在历史Activity
的列表中,当某种情况下我们不希望用户通过历史列表回到我们的Activity
的时候这个标记比较有用。它等同于在XML中指定Activity的属性android:excludeFromRecents="true"
。
action
的匹配要求Intent
中的action
存在且必须和过滤规则中的一个action
相同。区分大小写。
如果Intent
中含有category
,那么所以的category
都必须和过滤规则中的其中一个category
相同。
如果Intent
中不含有category
,那么也能匹配,因为系统在调用startActivity
或者startActivityForResult
的时候会默认为Intent
加上“android.intent.category.DEFAULT
”这个category
,所以为了我们的Activity
能够接收隐式调用,就必须在intent-filter
中指定“android.intent.category.DEFAULT
”。
规则与action
相似。
<intent-filter>
<data android:mimeType="image/*"/>
...
</intent-filter>
以上规则说明Intent
中的mimeType
属性必须为“image/*
”才能匹配。虽然没有定义URI
,但是还是得有默认值,URI
的默认值为content
和file
。也就是说没有URI
也得在Intent
中的URI
部分的schema
必须为content
或者file
才能匹配。
intent.setDataAndType(uri.parse("file://abc"),"image/png");
如果要为Intent指定完整的data,必须调用setDataAndType方法,不能先调用setData再调用setType。因为这两个方法会彼此清除对方的值。源码如下:
public Intent setData(Uri data){
mData = data;
mType = null;
return this;
}
而data
的结构略微复杂,语法如下:
<data android:scheme="string" android:host="string" android:port="string" android:path="string" android:pathPattern="string" android:pathPrefix="string" android:mimeType="string"/>
data
由两部分组成,mimeType
和URI
。
mimeType
指媒体类型,例如image/jpeg、audio/mpeg4-generic和video/*等。
URI
的结构如下:
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
<intent-filter>
<action android:name="com.dimon.1"/>
<action android:name="com.dimon.2"/>
<category android:name="com.dimon.1a"/>
<category android:name="com.dimon.2b"/>
<category android:name="android.intent.category.DEFAULF"/>\
<data android:mimeType="text/plain"/>
</intent-filter>
Intent intent = new Intent("com.dimon.1");
intent.addCategory("com.dimon.2b");
intent.setDataAndType(Uri.parse("file://abc"),"text/plain");
startActivity(intent);
使用隐式方式启动Activity
时,最好做一下判断,看看是否有Activity
能够匹配我们的隐式Intent
。
方法有两个:采用PackageManager
的resolveActivity
方法或者Intent
的resolveActivity
方法,如果他们匹配不了就返回null
。
另外PackageManager
还提供了queryIntentActivities
方法:它不是返回最佳匹配的Activity
信息而是返回所有成功匹配的Activity
信息。
public abstract List<ResolveInfo> queryIntentActivities(Intent intent, int flags);
public abstract ResolveInfo resolveActivity(Intent intent, int flags);
第二个参数我们使用MATCH_DEFAULT_ONLY
这个标记位,这个标记位仅仅匹配那些在intent-filter
中声明了<category android:name="android.intent.category.DEFAULT"/>
这个category
的Activity
。
只要上述两个方法不返回null
,那么startActivity
一定可以成功。因为不含有DEFAULT
这个category
的Activity
是无法接收隐式Intent
的。
上一篇是整理昨天的笔记,这是今天的读书笔记。其实吧,说是笔记,其实只是在转载知识点,可以说也没办法加入的自己的理解。可以说,笔记里的知识对于我来说都是新的知识,所谓的撰写笔记只是为了加深自己的印象,方便以后查找。
之后可能还会整理一些项目的笔记,那些项目就可能会加上自己粗浅的理解了。
我是一名大四学生,正在找工作,如果您有Android方面的工作,欢迎联系我~
您在阅读我的笔记时,如果发现错误,渴望您及时指出~谢谢~
千里之行始于足下,我只是一个蹒跚学步的小娃娃,在巨人的肩膀上祈求能走得更远。