IntenterFilter的匹配规则
启动Activityf分两种,显示调用和隐士调用;显示需要明确指定被启动对象的组件信息,包括包名和类名,而隐士调用则不需要明确指定组件信息;原则上一个Intent不应该既是显示调用又是饮食调用,二者共存的话以显示调用为主。
隐式调用需要Intent能匹配目标组件的IntentFilter中所设置的过滤信息,如果不匹配将无法启动目标Activity;IntentFilter中的过滤信息有action,category,data。示例:
<activity
android:name="com.ryg.chapter_1.ThirdActivity"
android:configChanges="screenLayout"
android:label="@string/app_name"
android:launchMode="singleTask"
android:taskAffinity="com.ryg.task1" >
<intent-filter>
<action android:name="com.ryg.charpter_1.c" />
<action android:name="com.ryg.charpter_1.d" />
<category android:name="com.ryg.category.c" />
<category android:name="com.ryg.category.d" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
一个过滤表中action,categroy和data可以有多个,一个Intent同时匹配action类型,category类别,data类别才算完全匹配,只有完全匹配才能成功启动目标Activity。一个Activity中可以有多个intent-filter;一个Intent只要能匹配任何一组intent-filter即可启动对应Activity。
1.action的匹配规则
action是一个字符串;action的匹配要求intent中的action存在且必须和过滤规则中的一个action相同,可以有多个,但必须有,一个相同就可以;值得注意:区分大小写。
2.category的匹配规则
category是一个字符串,与action匹配规则不同;要求如果intent中含有category;那么多有category都必须和过滤条件其中一个category相同;如果没有category,也是可以成功的,因为有默认的category“android.intent.category.DEFAULT”;
3.data的匹配条件
与action类似;data由两部分组成mimeType和URI.mineType指媒体类型,比如image/jpeg、audio/mpeg4-generic和video/*等,可以表示图片,文本,视频等不同媒体格式,而URI中包含的数据比较多,结构是:
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
Scheme:Uri的模式,比如http、file、Content等,如果没有这个其他参数无效,所以说必须指定;默认值是file
Host:Uri的主机名,比如www.baidu.com,如果host没有指定,那么整个Uri其他参数无效
Post:Uri端口号,比如80,仅当有scheme和host参数时候port参数才有意义
剩下三个参数表示路径信息。
要求Intent中必须含有data数据并且能够完全匹配某一个data.
当隐式启动一个Activity时候,可以做判断看是否有Activity能匹配我们的隐士intent,判断方法:采用PackageManager的resolveActivity方法或者Intent的resolveActivity;如果找不到匹配的Activity就会返回null。
Activity的启动过程
首先说两句体外话,Android的四大组件中除了BroadcastReceiver以为,其他三个组件必须在AndroidManifest中注册,对广播来说可以动态注册也可以静态注册;调用方式上来说,Activity、Service、BroadcastReceiver需要借住Intent,而ContentProvider则无需借住Intent。
Activity的工作过程
概述:Activity启动请求由Instrumentation处理,它通过Bind而向AMS(ActivityManagerService)发送请求,AMS维护一个ActivityStack负责栈内Activity的状态同步,AMS通过ActivityThread同步Activity状态从而完成Activity的生命周期方法调用。
从startActivity方法开始,startActivity方法有好多中重载方式,但最终都是调用startActivityForResult方法;
其中通过Instrumentation的exexStartActivity(其中会调用checkStartActivityResult方法,作用检查启动Activity的结果,没有在配置文件中注册的话,就会在这报错)方法,真实实现是ActivityManagerNative.getDefault()的startActivity方法完成(ActivityManagerNative是继承Binder并且实现了IActivityManager这个Binder接口);具体实现在AMS(采用单例模式对外提供)中的StartActivity;AMS中维护着ActivityStack,先通过ActivityStackSupervisor的startActivityMayWait方法,进而调用startActivityLocked方法>>调用startActivityUncheckedLocked方法调用到ActivityStack的resumeTopActivitieslocked方法(从ActivitySackSupervisor转移到了ActivityStack)>>但又调用了ActivitySackSupervisor中的startSpecificActivityLocked方法>>调用realStartActivityLocked方法(又回到ActivitySackSupervisor);
其中有个重要部分app.thread,他的类型为IApplicationThread,这个Binder接口的实现者完成大量和Activity以及Service启动/停止相关功能;它的实现者:ApplicationThread(ActivityThread的内部类);那么Activity的启动最终来到ApplicationThread中,通过scheduleLaunchActivity方法启动Activity,该方法主要是发送一个请求Activity的消息交给handler(H)处理;然后又ActivityThread的handleLaunchActivity方法实现,调用performLaunchActivity最终完成Activity对象的创建和启动过程。
performLaunchActivity方法主要完成几个事情:
1.从ActivityClientRecord中获取待启动的Activity的组件信息
2.通过Instrumentation的newActivity方法使用类加载器创建Activity对象
3.通过LoadedApk的makeApplication方法来尝试创建Application对象(注意没有创建,有了不创建,一个应有只有一个)
4.创建Contextimpl对象并通过Activity的attach方法完成一些重要数据的初始化
5.调用Activity的onCreate方法