Activity的生命周期和启动模式

activity的生命周期


onCreate()Activity正在被创建,生命周期的第一个方法,可以做一些初始化工作,比如调用setContentView去加载页面布局,初始化Activity所需数据等。
onStart():表示正在被启动,此时已经可见(Activity已经显示出来,只是我们看不到),但是还没有出现在前台,还无法和用户交互(无焦点)。
onResume () Activity已经可见并开始在前台活动(获得焦点)。
onRestart () Activity重新启动,当前Activity从不可见重新变为可见状态(没有被销毁)。
onPause () Activity正在停止,正常情况会紧接着onStop()会被调用。 可以存储数据、停止动画等,不能太耗时
onStop () Activity即将停止,可以做一些稍微重量级的回收工作,不能太耗时
onDestory () Activity即将被销毁,可以做一些回收工作和最终的资源释放

1,正常打开单个Activity,然后退出应用:

这种情况是最普通的状况,Activity的生命周期会按照上图从上到下的方式走。即:onCreate --> onStart --> onResume --> 运行--> 按返回键结束程序--> onPause-->onStop-->onDestory

2,打开一个Activity A,然后再打开另一个Activity B

对于A:onCreate --> onStart --> onResume --> A运行 --> A发出打开B的Intent --> onPause-->B可见-->onStop

此时,会打开B,B同样会经历一个完整的Activity生命周期。等B结束,A再度可见的时候,A会经历:

onRestart-->onStart-->onResume

注意,B这个Activity是在A的onPause执行后才变成可见状态的,所以为了不影响B的显示,最好不要在onPause里执行一些耗时操作,可以考虑将这些操作放到onStop里,这时B已经可见了。

3,优先级低的Activity被系统回收

Activity优先级从高到低大致有三种:

1),前台Activity。可见的前台Activity优先级最高

2),可见,但非前台的Activity。例如弹出了一个对话框,Activity可见,但是不可与用户交互。此类别优先级低一些。

3),后台Activity。这个就是不可见的Activity。

系统资源不足时,会优先回收优先级低的Activity。这个时候被结束的Activity,并不会像正常的Activity一样,在销毁的时候会走onPause,onStop,onDestory这样的生命周期,而是会多一个onSaveInstanceState的方法来保存一些数据。这个方法会在onStop前调用,但是不确定是在onPause之前还是之后。Activity重建的时候,这个方法中所保存的数据会以Bundle的形式作为参数传递给onCreate,所以我们可以用参数来判断这个Activity是新建的还是重建的,如果是重建的,则可以从Bundle中取出数据来恢复界面。


Activity生命周期切换过程 
  1. 针对一个特定的Activity,第一次启动,回调如下:onCreate-onStart-onResume
  2. 当用户打开新的Activity或者切换到桌面的时候,回调如下:onPause-onStop。如果新的Activity采用了透明主题,那么当前Activity不会回调onStop。
  3. 当用户再次回到原Activity,回调如下:onRestart-onStart-onResume。
  4. 当用户按back回退键时,回调如下:onPause-onStop-onDestroy
  5. onStart和onStop是从Activity是否可见这个角度来回调的,而onResume和onPause是从Activity是否位于前台这个角度来回调的。
  6. 从Activity A跳转到Activity B,Activity A的onPause先执行,Activity B的onResume在执行。
  7. onActivityResult() 和onResume()的调用顺序问题,回到调用activity时会马上执行onActivityResult方法,然后才是onResume()方法。

打开应用时先后执行了onCreate()->onStart()->onResume三个方法,
当我们按BACK键时,我们这个应用程序将结束,这时候我们将先后调用onPause()->onStop()->onDestory()三个方法
当我们按HOME的时候,Activity先后执行了onPause()->onStop()这两个方法,这时候应用程序并没有销毁。 先后分别执行了onRestart()->onStart()->onResume()三个方法

  1. 异常情况下的生命周期分析

    1. 资源相关的系统配置发生改变导致Activity被杀死并重新创建 
      在Activity异常终止的情况下,Activity被重新创建后,系统会调用 onSaveInstanceState ,并且把Activity销毁时onSaveInstanceState 方法所保存的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate()方法,我们可以通过上述两个方法判断Activity是否被重建了,如果重建了,我们可以取出数据并恢复,从时序上来讲,onRestoreInstanceState的调用时机在onStart之后。 
      在onSaveInstanceState 和onRestoreInstanceState方法中,系统自动为我们做了一定的恢复工作,系统会默认为我们保存当前Activity的视图结构,并且在Activity重启后为我们恢复这些数据,比如文本框输入的数据、ListView滚动的位置等。 
      onRestoreInstanceState和onCreate()方法的区别是,onRestoreInstanceState一旦被调用,其参数一定是有值的,官方建议使用这种方法去恢复数据,onCreate()`不行。
  2. 资源内存不足导致低优先级的Activity被杀死 
    Activity的优先级从高到低: 
    1. 前台Activity — 正在和用户交互的Activity,优先级最高 
    2. 可见但非前台的Activity — 比如Activity中弹出一个对话框,导致Activity可见但是位于后台无法和用户直接交互。 
    3. 后台Activity — 已经被暂停的Activity,比如执行了onStop,优先级最低。

      当系统内存不足的时候,系统会按照上述优先级杀死Activity所在的进程,并通过onSaveInstanceStateonRestoreInstanceState方法来存储和恢复数据。如果一个进程没有在4大组件执行,进程很快会被系统杀死。 
      当系统配置发生改变后,Activity会被重新创建,我们可以给Activity指定configChanges属性,Activity不会被重新创建,没有调用onSaveInstanceStateonRestoreInstanceState方法,取而代之的是调用onConfigurationChanges方法,如下所示: 
    Android:configChanges="orientation | keyboardHidden 

    主要有如下四个重要属性: 

local 设备的本地位置发生改变,一般指切换了系统语言 
orientation屏幕方向发生了改变,比如旋转了屏幕
screenSize 屏幕尺寸发生了变化,旋转屏幕尺寸时设备发生了变化
keyboardHidden键盘的可访问性发生了改变,比如用户调出键盘
补充: 

横竖屏切换时候Activity的生命周期: 
  不设置Activity的android:configChanges时,切屏会重新回掉各个生命周期,切横屏时会执行一次,切竖屏时会执行两次 
  设置Activity的android:configChanges=”orientation”时,切屏还是会调用各个生命周期,切换横竖屏只会执行一次 
  设置Activity的android:configChanges=”orientation |keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法


关于Activity横竖屏切换的声明周期变化:
1、新建一个Activity并把各个生命周期打印出来
2、运行Activity,得到如下信息
onCreate-->onStart-->onResume-->
3、切换成横屏时
onSaveInstanceState-->onPause-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume-->
4、切换成竖屏时,
onSaveInstanceState-->onPause-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume-->onSaveInstanceState-->onPause-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume-->
5、修改AndroidManifest.xml,把该Activity添加 android:configChanges="orientation",执行步骤3
onSaveInstanceState-->onPause-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume-->
6、再执行步骤4,发现不会再打印相同信息,但多打印了一行onConfigChanged
onSaveInstanceState-->onPause-->onStop-->onDestroy-->onCreate-->onStart-->onRestoreInstanceState-->onResume-->onConfigurationChanged-->
7、把步骤5的android:configChanges="orientation" 改成 android:configChanges="orientation|keyboardHidden",执行步骤3,就只打印onConfigChanged
onConfigurationChanged-->
8、执行步骤4
onConfigurationChanged-->
onConfigurationChanged-->

总结:
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
总结一下整个Activity的生命周期
补充一点,当前Activity产生事件弹出Toast和AlertDialog的时候
ActivityActivity的生命周期不会有改变运行时按下HOME键(跟被完全覆盖是一样的):onSaveInstanceState --> onPause --> onStop       onRestart -->onStart--->onResume
Activity未被完全覆盖只是失去焦点:onPause--->onResume

 Activity的启动模式
  1. standard:标准模式 
      系统的默认模式,每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在。被创建的生命周期符合典型情况下的生命周期,它的onCreate、onStart、onResume都会调用。在这种模式下,谁启动了这个Activity,那么这个Activity就运行在启动它的那个Activity栈中。比如Activity A启动了Activity B(B是标准模式),那么B就会进入到A所在的栈中。使用场景大多数Activity。
  2. singleTop:栈顶复用模式 
      如果新Activity已经位于任务栈的栈顶,那么次Activity不会被重新创建,同时它的onNewIntent方法会被回调,通过此方法我们可以取出当前请求的信息。这个Activity的onCreate、onStart不会被调用,因为它并没有发生改变。使用场景如新闻类或者阅读类App的内容页面。
  3. singleTask:栈内复用模式 
      一种单实例模式,只要Activity在一个栈中存在,多次启动Activity都不会重新创建实例,系统会回调onNewIntent方法。当设置此模式后,比如Activity A会首先寻找是否存在A想要的任务栈,如果不存在就重新创建一个任务栈,如果存在,就看A是否在栈中有实例存在,如果有实例存在那么系统就会把A调到栈顶并调用onNewIntent方法,同时由于singleTask默认具有clearTop的效果,就会导致栈内所有在A上面的Activity全部出栈,如果不存在,就创建A的实例并把A压入栈中。使用场景如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。
  4. singleInstance:单实例模式 
      这是一种加强的singleTask模式,除了具有singleTask所有特性外,还具有此种模式的Activity A只能单独的位于一个新的任务栈,然后A单独在这个栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity。使用场景如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。
  5. Activity的Flags 
    1. 设置启动模式的两种方式 
      通过AndroidMenifest为Activity指定启动模式 
      android:launchMode="singleTask" 
      Intent中设置标记为来为activity指定启动模式 
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    2. 常用标记位 
      FLAG_ACTIVITY_NEW_TASK 
      为Activity指定singleTask启动模式 
      FLAG_ACTIVITY_SINGLE_TOP 
      为Activity指定singleTop启动模式 
      FLAG_ACTIVITY_CLEAN_TOP 
      具有此标记位的Activity,当它启动时,同一个任务栈中所有位于它上面的Activity都要出栈。 
      FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 
      不希望用户通过历史列表回到我们的Activity的时候这个标记比较有用,等同于在XML中指定Activity的属性android:excludFromRecents="true".
3. IntentFilter的匹配规则

为了匹配过滤列表,需要同时匹配过滤列表中的action、category、data信息,否则匹配失效。一个过滤列表中的action、category和data可以有多个。一个Intetn同时匹配action类别、category类别、data类别才算完全匹配,只有完全匹配才能启动目标Activity。一个Activity中可以有多个intent-filter,一个Intent只要匹配其中任何一组intent-filter即可成功启动对应的Activity。 
1. action的匹配规则 
  action是一个字符串,系统预定义了一些action,我们也可以自定义action,匹配规则是Intent中的action必须能够和过滤规则中的action匹配,一个过滤规则中可以有多个action,那么只要Intent中的action能够和过滤规则中的任何一个action相同即可匹配成功,Intent中的action存在且必须和过滤规则中的其中一个action相同。 
2. category的匹配规则 
  category是一个字符串,系统预定义了一些category,我们也可以在应用中定义自己的category。category和action的匹配规则不同,要求Intent中如果含有category,那么所有的category都必须和过滤规则中(即intent filter中设置的category)的其中一个相同。Intent也可以没有category,如果没有category的话,在startActivity或者startActivityForResult的时候会默认为Intent加上"android.intent.category.DEFAULT" 。 
3. data的匹配规则 
  如果过滤规则中添加了data,那么Intent中必须也要定义可匹配的data。data的语法如下所示:

<code class="hljs haskell has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <<span class="hljs-typedef" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">data</span> </span>
       android:scheme=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"string"</span>
       android:host=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"string"</span>
       android:port=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"string"</span>
       android:path=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"string"</span>
       android:pathPattern=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"string"</span>
       android:pathPrefix=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"string"</span>
       android:mimeType=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"string"</span> /></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

  data由两部分组成,mineType和URI。mineType指媒体类型,比如image/jpeg、audio/mpeg4-generic和video/*等,可以表示图片、文本、视频等不同媒体格式,而URI包含的数比较多,一个URI结构如下所示

<code class="hljs ruby has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><scheme><span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">://<host></span><span class="hljs-symbol" style="color: rgb(0, 102, 102); box-sizing: border-box;">:<port>/</span>[<path>|<pathPrefix>|<pathPattern>]</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

下面举个实际的例子大家就明白了:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-label" style="box-sizing: border-box;">content:</span>//<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.example</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.project</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>/folder/subfolder/etc</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

其中: 
- Scheme:URI的模式,比如http、file、content等,如果URI中没有指定scheme,那么整个URI的其他参数无效,即URI也是无效的; 
- Host:URI的主机名,如com.example.project,如果host未指定,那么整个URI中的其他参数无效,即URI也是无效的; 
- Port:URI中的端口号,如200,只有URI中指定了scheme和host参数的时候port参数才有意义; 
- Path、PathPattern和PathPrefix:这三个参数表示路径信息,如folder/subfolder/etc,其中path表示完整的路径信息;PathPattern也表示完整的路径信息,但是它里面可包含通符“*”,表示0个或多个任意字符;PathPrefix表示路径的前缀信息。 
data匹配规则:

<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">            <intent-filter>
                <data android:mimeType=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"image/*"</span>/>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>
            </intent-filter></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

这种规则制定了媒体类型为所有类型的图片,那么Intent中mimeType属性必须为”image/*”才能匹配,这种情况下没有指定URI,但是Intent中的URI部分的schema必须为content或者file才能匹配,我们需要在Intent中这样指定: 
intent.setDataAndType(Uri.parse("file://abc"), "image/png") 
如果要为Intent指定完整的data,必须要调用setDataAndType方法,不能先调用setData再调用setType,因为这两个方法彼此会清除对方的值。 
怎么判断是否有Activity是否能够匹配我们的隐式Intent? 
1. 采用PackageManagerresolveActivity方法或者Intent的resolveActivity方法,如果找不到就返回null。 
2. PackageManager方法还提供了queryIntentActivities方法,这个方法和resolveActivity方法最大的不同是,它不是返回最佳匹配的Activity的信息,而是返回的是所有成功匹配的Activity信息。我们可以看一下方法的原型:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> List<ResolveInfo> <span class="hljs-title" style="box-sizing: border-box;">queryIntentActivities</span>(Intent intent,@ResolveInfoFlags <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> flags);
 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">abstract</span> ResolveInfo <span class="hljs-title" style="box-sizing: border-box;">resolveActivity</span>(Intent intent, @ResolveInfoFlags <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> flags);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

上述两个方法的第二个参数注意,我们要使用MATCH_DEFAULT_ONLY这个标记位,只能匹配intent-filter中声明了<category android:name="android.intent.category.DEFAULT"/>这个category的Activity。使用这个标记位最大的意义是上述两个方法不返回null,那么startActivity一定可以成功。如果不使用这个标记位,就可以吧intent-filter中category不含DEFAULT的那些Activity匹配出来,startActivity有可能失败,不含有DEFAULT这个category的Activity是无法接受隐式Intent的。 
3. 在action和category中有一类比较重要,用来标注一个入口:

<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">action</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"android.intent.action.MAIN"</span> /></span>

<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">category</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"android.intent.category.LAUNCHER"</span> /></span></code>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值