Intent连接不同组件的原理

Android中Intent连接不同组件的原理

 

一、什么是Intent

1、概念

Intent翻译过来是”意图、目的”的意思,是连接四大组件的桥梁,作为中介传输信息.

2、类型

Intent分为两种,显示和隐示.显示需要指定目标组件信息,隐示则只需要指定被目标组件响应的信息(action和category等信息).

3、属性

component(组件):目的组件 
action(动作):用来表现意图的行动 
category(类别):用来表现动作的类别 
data(数据):表示与动作要操纵的数据 
type(数据类型):对于data范例的描写 
extras(扩展信息):扩展信息 
Flags(标志位):期望这个意图的运行模式 

二、连接不同组件的原理

这里以Activity里启动Service为例,来分析原理.

Intent intent = new Intent(MainActivity.this, MainService.class); startService(intent);
       
       
  • 1

1、点击跳转到Intent带有这两个参数的构造方法

    public class Intent implements Parcelable, Cloneable {
            ...... 
    public Intent(Context packageContext, Class<?> cls) {
        mComponent = new ComponentName(packageContext, cls);
    }       
            ...... 
            }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里只是新建了ComponentName实例.

2、好,回到startService(intent),点击会跳转到ContextWrapper类

public class ContextWrapper extends Context {
     Context mBase; 
     ...... 
     @Override public ComponentName startService(Intent service) { 
     return mBase.startService(service); 
     } 
     ...... 
     }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3、在这个方法里调用mBase的startService方法,这个mBase其实是ContextIml的实例,ContextIml也继承自Context,代码位于/frameworks/base/core/java/android/app/ContextImpl.java。 
这里顺便介绍下Context、ContextWrapper 、ContextImpl的关系.直接 
放图吧。

这里写图片描述 

4、好,继续看ContextImpl类中的startService实现. 
PS:给大家推荐一个在线看源码的网站 点击打开

class ContextImpl extends Context { 
            ...... 
            @Override 
            public ComponentName startService(Intent service) {
                try {
                    service.setAllowFds(false); 
                    ComponentName cn=ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver())); 
                    if (cn != null && cn.getPackageName().equals()) { 
                        throw new SecurityException( + service + + cn.getClassName()); 
                        } 
                    return cn; 
                    } catch (RemoteException e) {
                        return null; 
                        } 
                } 
            ...... 
            }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

5、在这里调用了ActivityManagerNative的getDefault方法返回的是gDefault.get()方法.

public abstract class ActivityManagerNative extends Binder implements IActivityManager {
            ...... 
            static public IActivityManager getDefault() {
                return gDefault.get(); 
                } 
            ......
        }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

6、gDefault.get()方法返回的是IActivityManager对象.IActivityManager是一个Binder对象.

{ 
            ...... 
            private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
                protected IActivityManager create() {
                    IBinder b = ServiceManager.getService();
                    if (false) {
                        Log.v(, + b); 
                        } 
                    IActivityManager am = asInterface(b); 
                    if (false) {
                        Log.v(, + am); 
                        } 
                    return am; 
                    } 
                }; 
            ...... 
                }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

7、回到第4步.

ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()));
       
       
  • 1

调用了IActivityManager的startService方法,IActivityManager是一个抽象类,由它的实现类ActivityManagerProxy来实现.

8、看下它的实现

class ActivityManagerProxy implements IActivityManager { 
            ...... 
            public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType) throws RemoteException { 
                Parcel data = Parcel.obtain(); 
                Parcel reply = Parcel.obtain(); 
                data.writeInterfaceToken(IActivityManager.descriptor); 
                data.writeStrongBinder(caller != null ? caller.asBinder() : null); 
                service.writeToParcel(data, 0); 
                data.writeString(resolvedType); 
                mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0); 
                reply.readException(); 
                ComponentName res = ComponentName.readFromParcel(reply); 
                data.recycle(); 
                reply.recycle(); 
                return res; 
                } 
            ...... 
            }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

startService传入是三个参数:IApplicationThread 、Intent 、resolvedType.

第一个参数IApplicationThread是一个接口, 由主进程ActivityThread创建的一个Binder对象.第二个参数Intent 不用说了第三个参数是Intent 的MIME类型

9、接下来关键的一行代码

mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0); 
       
       
  • 1

这个transact方法会进入Binder驱动程序.Binder驱动程序唤醒正在等待的ActivityManagerService进程,最后进入到ActivityManagerService的startService函数中。

public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
            { 
                ...... 
                public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType) {
                    // Refuse possible leaked file descriptors 
                    if (service != null && service.hasFileDescriptors() == true) {
                        throw new IllegalArgumentException(); 
                        } 
                    synchronized(this) {
                        final int callingPid = Binder.getCallingPid(); 
                        final int callingUid = Binder.getCallingUid(); 
                        final long origId = Binder.clearCallingIdentity(); 
                        ComponentName res = startServiceLocked(caller, service, resolvedType, callingPid, callingUid); Binder.restoreCallingIdentity(origId); return res; 
                        } 
                    } 
                ...... 
                }
                }
            }
        }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

10、从Binder里获取到pid和uid,添加这两个参数到startServiceLocked方法.

public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
            { 
                ...... 
                ComponentName startServiceLocked(IApplicationThread caller,Intent service, String resolvedType,int callingPid, int callingUid) { 
                    ...... 
                    ServiceLookupResult res =retrieveServiceLocked(service, resolvedType,callingPid, callingUid); 
                    ServiceRecord r = res.record; 
                    ...... 
                    return r.name; 
                    } 
                ...... 
                }
        }
       
       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

11、在这个方法里,调用retrieveServiceLocked方法解析service这个Intent.至此,Intent的使命基本结束了,我就不继续追踪服务的启动了.大家感兴趣可以自己往下跟踪.

三、总结

Intent是作为一个参数,携带相关的信息.

1、由主进程通过Binder进入AMS进程 
2、 在AMS进程获取和管理要启动的服务的相关信息 
3、 由AMS进程回到该主进程启动服务

而Intent一直是贯穿始终的.

最后附上从网上找到的整个流程图,,帮大家理

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值