activity启动模式
1.SingleTop
栈顶复用,当Activity位于栈顶的时候在启动该Activity,那么这个Activity不会被重新创建,会调用onNewIntent(Intent intent)
,如果不在栈顶,则跟默认的启动模式一样,会重新创建。
2.SingleTask
栈内复用,当Activity已经创建过,且存在栈内了,当再启动该Activity,那么会把该Activity上面所有Activity都退出栈,并调用onNewIntent(Intent intent)
方法
3.SingleInstance
新的任务栈,当以这种模式启动,会创建一个新的ActivityTask存放这个Activity
4.Standard
默认模式,你只要启动 我就给你创建,并压入栈内。
虽然
SingleTask,SingleTop
都可能会复用Activity,但是注意的是SingleTop
是栈顶复用。
activity的flag
以下摘自intent源码
-
FLAG_ACTIVITY_NO_HISTORY
/**
* If set, the new activity is not kept in the history stack. As soon as
* the user navigates away from it, the activity is finished. This may also
* be set with the {@link android.R.styleable#AndroidManifestActivity_noHistory
* noHistory} attribute.
*
*If set, {@link android.app.Activity#onActivityResult onActivityResult()}
* is never invoked when the current activity starts a new activity which
* sets a result and finishes.
*/
当标记该FLAG后启动的activity是不会在存在ActivityTask ,例如A启动B,B启动C,C finish()后看到的界面是A,这个时候B也同时被 finish()了
-
FLAG_ACTIVITY_SINGLE_TOP
singleTop设置后形势与启动模式SingleTop一致
-
FLAG_ACTIVITY_NEW_TASK
标志启动在一个新的Task中。当与FLAG_ACTIVITY_CLEAR_TOP一起用,与启动模式SingleTask一致FLAG_ACTIVITY_MULTIPLE_TASK, 消除FLAG_ACTIVITY_NEW_TASK这个标志位的FLAG_ACTIVITY_CLEAR_TOP,清除这个activity栈顶的所有activity
-
FLAG_ACTIVITY_FORWARD_RESULT
/**
* If set and this intent is being used to launch a new activity from an
* existing one, then the reply target of the existing activity will be
* transfered to the new activity. This way the new activity can call
* {@link android.app.Activity#setResult} and have that result sent back to
* the reply target of the original activity.
*/
这个标志位用于A启动B,B启动C,C要把result返回给A,这个时候B启动C的时候带上这个标志位就可以了。这个时候C finish()的时候必须带上 setResult 方法,否则系统会抛出异常。
-
FLAG_ACTIVITY_PREVIOUS_IS_TOP
即 A---> B --->C,若B启动C时用了这个标志位,那在启动时B并不会被当作栈顶的Activity,而是用A做栈顶来启动C。
此过程中B充当一个跳转页面。典型的场景是在应用选择页面,
如果在文本中点击一个网址要跳转到浏览器,而系统中又装了不止一个浏览器应用,
此时会弹出应用选择页面。在应用选择页面选择某一款浏览器启动时,就会用到这个Flag。
然后应用选择页面将自己finish,以保证从浏览器返回时不会在回到选择页面。
经常与FLAG_ACTIVITY_FORWARD_RESULT 一起使用。
-
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,
-
FLAG_ACTIVITY_BROUGHT_TO_FRONT,
-
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,
-
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY,
-
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET,
-
FLAG_ACTIVITY_NEW_DOCUMENT,
-
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET,
以上这些要么是系统用的,要么是不常用,不做解释了
-
FLAG_ACTIVITY_NO_USER_ACTION,
禁止activity调用onUserLeaveHint()。onUserLeaveHint()作为activity周期的一部分,它在activity因为用户要跳转到别的activity而退到background时使用。比如,在用户按下Home键(用户的操作),它将被调用。比如有电话进来(不属于用户的操作),它就不会被调用。注意:通过调用finish()时该activity销毁时不会调用该函数。
-
FLAG_ACTIVITY_REORDER_TO_FRONT,
/**
* If set in an Intent passed to {@link Context#startActivity Context.startActivity()},
* this flag will cause the launched activity to be brought to the front of its
* task's history stack if it is already running.
*
*For example, consider a task consisting of four activities: A, B, C, D.
* If D calls startActivity() with an Intent that resolves to the component
* of activity B, then B will be brought to the front of the history stack,
* with this resulting order: A, C, D, B.
*
* This flag will be ignored if {@link #FLAG_ACTIVITY_CLEAR_TOP} is also
* specified.
*/
注释说的很清楚 就是把要启动的放到最栈顶 但是与FLAG_ACTIVITY_CLEAR_TOP相冲突
-
FLAG_ACTIVITY_NO_ANIMATION
启动不带动画
-
FLAG_ACTIVITY_CLEAR_TASK
全部清空栈
-
FLAG_ACTIVITY_TASK_ON_HOME
该flag启动的activity,点击返回键会回到launcher.需要与
FLAG_ACTIVITY_NEW_TASK
一起使用,并且FLAG_ACTIVITY_NEW_TASK
模式生效(参考该属性)后,该flag才会起作用. FLAG_ACTIVITY_RETAIN_IN_RECENTS,与activity设置autoRemoveFromRecents = false属性效果一样.是指当前activity销毁后,是否还在概览屏幕中显示.(5.0之后生效)
-
说明
以上参考Intent源码注释,《Android开发艺术探索》以及 这篇文章
IntentFilter匹配规则
启动Activity有隐式和显式2中方式,这里首先简单说一下显式启动
显式启动Activity
Intent intent = new Intent();
intent.setClass(@NonNull Context packageContext, @NonNull Class> cls)
context.startActivity(intent);
这里是简单的调用intent启动activity,一般是不会出错,但是如果启动系统的activity,容易启动失败,这个时候 就需要intent.resolveActivity()
来确定这个activity是否能够安全启动,当不反回为null的时候就可以安全启动。
resolveActivity 的源码如下
核心方法就是这个
ResolveInfo info = pm.resolveActivity(
this, PackageManager.MATCH_DEFAULT_ONLY);
会去遍历满足条件的activity的返回回来,
PackageManager.MATCH_DEFAULT_ONLY
这个的作用就是只返回Action和Category满足的activity。
隐式启动Activity
隐式启动需要在activity的标签内设置Intent-filter来过滤对应的activity。
如图所示的intent-filter,这里按照字母顺序说明一下
-
Action
action 决定跳转的方向,也是自己可以制定的筛选规则,就如我们常用的intent.getAction().equal("test")来决定我们的intent是否合适
action的匹配规则
简言之如果intent-filter中有多个action,那么只要隐式启动的intent中有一个能够对应上那么就能够匹配成功
-
Category
category这个是用系统的。默认的隐式启动的activity的intent-filter都要注明一个default这个category。
Category匹配规则
如果intent-filter中有多个category那么intent就必须要与每一个category都要相对应,换句话说就是 filter中有3个 那么intent中也必须有3个而且是一模一样的。但是默认的android.intent.category.DEFAULT
在startActivity时是不用添加的,在启动的时候 默认Android系统会在intent上自动设置这个category
-
Data
data是由2部分组成,URI 和mineType
图片里 除了mineType这个属性外 就都是URI的内容了
URI格式如下
栗子
http://www.baidu.com:80/search/info
scheme: URI的模式,重中之重,如果没有scheme那么整个data就无效了。
host:URI主机名,和scheme一样,一个data至少包含scheme和host
port:端口号
path,pathPattern,pathPrefix都是指路径,path是指完整路径,pathPattern也是完整路径,但是里面可以包括通配符“” “”表示0个或多个任意字符。pathPrefix表示路径的前缀信息。
接下来就是说明mineType
这里data就必须要指明mineType为“image/”,否则无法成功,另外就是有时候虽然data没有指明URI,但是他是有默认值的scheme是content或者是file,所以对于这里这个data的匹配规则就必须
intent.setDataAndType(Uri.parse("content://test"),"image/*"))
;
如果intent要设置data和type就必须要用这个setDataAndType,对于setData,setType会相互抵消另一个参数,
接下来说一下activity的声明周期
先总体说明一下
oncreate->onstart->onRestoreInstance->onResume->onPause->onSaveInstance->onStop->onDestory
其中oncreate,onDestory之后是前台生命周期,onResume到onPause是可见生命周期。
这里面我备注了很多,可以看下我分享出来的图1
图2
大家也可以按照我的思路对应着图的顺序照着源码走一遍
最有有什么问题,大家可以留言,加我微信探讨