一.Flag标志位
在阅读源码的时候经常发现有一些标志属性使用一些位操作来判断是否具有该标志,增加标志或者去除标志。
如:
为什么要使用16进制呢?为何不使用十进制0,1,2...?原因是因为这样就可以方便的用位运算来表示共同具有某些属性或者直接判断是否具有某个属性。
上面这句话我们稍微来分析一下。拿文件的权限来分析一下,我们知道文件有三个权限:读,写,执行。分别用4 , 2 , 1来表示,这样一来就可以很快速的知道文件所有的权限,比如5表示可读可执行两个权限,7表示可读可写可执行权限。
如果把上面的2进制换成10进制呢?结果就会变得很尴尬。假如上面三个权限分别用1 , 2 , 3表示,3这个就会很尴尬,因为我们不知道这个值表示的是可读可写两个权限还是仅仅一个执行权限。
Android源码中主要针对FLAG的运算有三种
①. 增加属性 "|"
如果需要向flag变量中增加某个FLAG,使用"|"运算符
flag |= XXX_FLAG;
原因: 如果flag变量没有XXX_FLAG,则 | 完后flag对应的位为1,如果有XXX_FLAG,则 | 完后值不会变对应位还是1.
②. 包含属性 "&"
如果需要判断flag变量中是否包含XXX_FLAG,使用"&"运算符
flag & XXX_FLAG != 0 或者 flag & XXX_FLAG = XXX_FLAG
原因: 如果flag变量里包含XXX_FLAG,则&完后flag变量对应的位为1,因为XXX_FLAG的定义保证了只有一位非0,其他位都为0,所以如果是包含的话&运算后值不为0,值为此XXX_FLAG的值,不包含的话值为0.
③.取消属性 "&~"
如果需要取消flag变量的XXX_FLAG, 使用 "&~".
flag &= ~XXX_FLAG;
原因: 先对XXX_FLAG进行取反 则XXX_FLAG原来非0的那一位变为0,则使用&运算符后flag变量非0的那一位变为0,则意味着flag变量不包含XXX_FLAG.
这样做的好处就是可以用一个值表示多种状态。假如这里有四种状态:是否可点击,是否获取焦点。我们只需用flag标记 : 0x1,0x2,0x4,0x8 , 然后保存到一个值里面就行,用以上的运算符就能快速的增加删除以及判断属性了。
二.addFlags (int flags)和setFlags (int flags)区别
Public Intent addFlags (int flags)
增加额外的标志到Intent(或者已经存在的flags值)
参数 flags 需要设置的新的flags
Returns(返回值)
返回相同Intent对象,用来将多个调用链接成一个调用的声明
public Intent setFlags (int flags)
设置特定的flags去控制Intent如何执行。大部分的values 依赖于正在被执行的Intent组件的类型,特别是FLAG_ACTIVITY_* 这些flags全部用在Context.startActivity() 和
FLAG_RECEIVER_* 这些flags全部用在 Context.sendBroadcast().
具体内容详情看task和back stack
参数 flags 设置要求的flags
Returns(返回值)
返回相同Intent对象,用来将多个调用链接成一个调用的声明
三.相关知识的理解
Task
Task就是一个任务栈,里面用来存放Activity,第一个进去的(Activity)处于栈的最下面,而最后创建的(Activity)则处于栈的最上面。从Task中取出(Activity)是从最顶端取出,也就是说先进后出,后进先出。而Activity在Task中的顺序是可以控制的,在Activity跳转时用到Intent Flag可以设置新建Activity的创建方式。
Back Stack
字面意思,是回退栈的意思,它属于数据结构中栈的一种。当从一个Activity 跳到另一个Activity的时候,如果不进行特殊的处理,就会有Activity被压入栈。当回退栈为空的时候,表示当前,已经到达了Lancher。因此,我们就可以知道BackStack就是一个存储Activity的容器,一般情况下,每需要执行一个Task,都至少有一个回退栈,这个容器中也至少有一个Activity实例。
LanchMode的作用和使用方法
点击以下文章:安卓启动Launch mode
例子:
在已经启动A,B,C,D四个Activity的情况下。再启动C的时候,不希望是ABCDC,而是AB,而且B上的数据需要保留
Intent it = new Intent(D.this,B.class);
it.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//设置可以关掉它所跳到的界面之外已经开启的activity在这里是把C关闭
it.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);//设置不要刷新即将跳转的页面
D.this.startActivity(it);
四.各Flag(标志)属性 详解
FLAG_GRANT_READ_URI_PERMISSION
如果设置了,Intent的接受者将被准许执行read操作(Intent 携带的URI数据和任何Clipdata中特定的URIs数据)的权限。
FLAG_GRANT_WRITE_URI_PERMISSION
如果设置了,Intent的接受者将被准许执行write操作(Intent 携带的URI数据和任何Clipdata中特定的URIs数据)的权限。
FLAG_GRANT_PERSISTABLE_URI_PERMISSION
当结合使用 flag_grant_read_uri_permission 和/或 flag_grant_write_uri_permission,URI权限授予可以坚持在设备重新启动直到明确撤销 用revokeuripermission(URI,int)。
FLAG_GRANT_PREFIX_URI_PERMISSION
当结合使用 flag_grant_read_uri_permission 和/或 flag_grant_write_uri_permission,URI权限授予适用于任何前缀匹配不同于原始的授予的URI。
FLAG_DEBUG_LOG_RESOLUTION
使能够使用调试功能的flag。设置之后,日志信息将在intent处理过程被输出,为了告诉你最后的解决列表被发现已创建。
FLAG_FROM_BACKGROUND
可以由调用者设置,以指示此意图来自后台操作,而不是来自直接用户交互.。
FLAG_ACTIVITY_BROUGHT_TO_FRONT
这个flag不能正常地被应用程序代码设置,而是系统为你设置由于在 launchMode 设置为singleTask模式
FLAG_ACTIVITY_CLEAR_TASK
如果通过 Context.startactivity()去设置/启动一个Intent,这个flag将导致任何存在的task,将与活动开始前清除的活动相关联.
FLAG_ACTIVITY_CLEAR_TOP
如果已设置,并且正在启动的活动已经在当前任务(backstack)中运行,那么,而不是启动该活动的新实例,而且它上面的所有其他活动都将被关闭,而这个意图将作为一个新的意图传递到(现在的顶部)旧活动中.。
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
这个常数是在API级别21废弃掉。在API 21执用 flag_activity_new_document 替代
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
如果设置,新活动不保存在最近启动的活动列表中。
FLAG_ACTIVITY_FORWARD_RESULT
如果设置这个intent是被用来从一个现有的acitivity启动到新的acitivity,现有activity的回复目标将被转移到新的activity。
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
这个flag不能正常地被应用程序代码设置,而是系统为你设置,如果这个活动正在展开的历史堆栈(长按 Home键)。
FLAG_ACTIVITY_MULTIPLE_TASK
此标志用来创建一个新的task和启动一个活动到此任务
FLAG_ACTIVITY_NEW_DOCUMENT
此标志用于将文档打开到一个新的任务中,该任务源于intent启动的活动。
FLAG_ACTIVITY_NEW_TASK
设置此标志使activity将成为此历史堆栈上新任务的开始
1.如果D这个Activity在Manifest.xml中的声明中添加了Task Affinity,系统首先会查找有没有和D的Task Affinity相同的Task栈存在,如果有存在,将D压入那个栈
2.如果D这个Activity在Manifest.xml中的Task Affinity默认没有设置,则会把其压入栈1,变成:A B C D,这样就和标准模式效果是一样的了。
FLAG_ACTIVITY_NO_ANIMATION
如果通过 Context.startactivity()去设置/启动一个Intent,这个标志将阻止系统执行一个活动去下一个活动的过渡动画。
禁用掉系统默认的Activity切换动画。
FLAG_ACTIVITY_NO_HISTORY
设置此标志activity将不添加到回退栈(backStack)
FLAG_ACTIVITY_NO_USER_ACTION
设置此标志,将阻止onuserleavehint()正常回调发生在当前最前的活动,在它被停下来作为新启动活动被带到前面。
FLAG_ACTIVITY_PREVIOUS_IS_TOP
如果设置并使用此意图从现有的一个activity a启动到新activity b,新avitivity b将不会被视为栈顶而是activity a,而是决定是否新意图传递到顶部而不是启动新的活动。
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
设置此标志使这个活动要么开始在一个新的任务或带到现有的任务的顶部,那么它将被启动作为任务的前门。
FLAG_ACTIVITY_REORDER_TO_FRONT
如果在通过 Context.startactivity()去设置/启动一个Intent,如果需要启动的activity已经运行,此标志使被启动的活动被带到任务的历史堆栈的前面.。
FLAG_ACTIVITY_SINGLE_TOP
如果设置,activity将不会被启动如果其正在backstack的栈顶
FLAG_ACTIVITY_TASK_ON_HOME
如果在通过 Context.startactivity()去设置/启动一个Intent,此flag将使新启动任务置于当前活动任务的顶部(如果只有一个task时)。
FLAG_RECEIVER_REGISTERED_ONLY
如果设置,当发送一个广播只有注册接收器将被调用,没有BroadcastReceiver组件将被启动。
FLAG_RECEIVER_FOREGROUND
当发送广播的时候设置了这个标志,会允许接收者以前台的优先级运行,有更短的时间间隔。正常广播的接受者是后台优先级,不会被自动提升。
FLAG_RECEIVER_REPLACE_PENDING
如果在发送广播时设置了这个标志,那新的广播会替换掉那些已存在的相同广播。相同的定义是通过Intent.filterEquals方法对两个广播的Intent处理返回true。 当匹配到相同的,新的广播和对应的接收器会将待发送的广播列表中已存在的替换掉,在列表中保留同样的位置。这个标志通常被粘性广播(Sticky Broadcast)使用,只保证将最新的广播的值传递给接收器。