Android应用程序启动(根Activity)过程,Android高级开发面试

本文详细解析了Android应用程序启动过程,从Activity的startActivityForResult方法开始,经由ActivityManagerService(AMS)到ApplicationThread,再到最终的ActivityThread启动Activity。涉及关键步骤包括AMS中的startActivity、Binder通信、ActivityRecord创建以及主线程的消息处理。
摘要由CSDN通过智能技术生成

public void startActivity(Intent intent, @Nullable Bundle options) {

if (options != null) {

startActivityForResult(intent, -1, options);

} else {

startActivityForResult(intent, -1);

}

}

都是走到 startActivityForResult()中去,其中第一个参数为在Launcher中创建的Intent,第二个参数-1表示Launcher不需要知道Activity启动的结果。也就是说Lancher只管发请求,之后怎么样就再也不处理了。我们来看看 startActivityForResult()的代码:

// Acitvity.java

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,

@Nullable Bundle options) {

// 1

if (mParent == null) {

options = transferSpringboardActivityOptions(options);

Instrumentation.ActivityResult ar =

mInstrumentation.execStartActivity(

this, mMainThread.getApplicationThread(), mToken, this,

intent, requestCode, options);

} else {

}

}

注释1:如果mParent==null 则往下走execStartActivity()

mParent是当前Activity的父类,因为根Activity还没有创建出来,所以mParent就是null。

接着调用 Instrumentation类的 execStartActivity(),传入参数:this(上下文)、但前应用主线程、token、this(上下文)、Launcher来的intent、requstCode(-1,表示无需知道后面的结果)、携带参数bundle。

接着我们来看看 Instrumentation这个类的启动Activity的方法:

public ActivityResult execStartActivity(

Context who, IBinder contextThread, IBinder token, String target,

Intent intent, int requestCode, Bundle options) {

try {

intent.migrateExtraStreamToClipData();

intent.prepareToLeaveProcess(who);

int result = ActivityManager.getService()

.startActivity(whoThread, who.getBasePackageName(), intent,

intent.resolveTypeIfNeeded(who.getContentResolver()), //1

token, target, requestCode, 0, null, options);

checkStartActivityResult(result, intent); //2

} catch (RemoteException e) {

throw new RuntimeException(“Failure from system”, e);

}

return null;

}

try{}中,先修改一下intent的内容。

其次在注释1中:调用 ActivityManager.getService().startActivity()一套组合拳。

这条代码先从 ActivityManager.getService()获取AMS在Client端的代理对象。也就是说,它会返回个可以看做是 AMS的对象。

然后调用其 startActivity(),也就是调用 ASM.startActivity()

我们先不进入到AMS的startActivity去,而是看看这个 AMS是怎么来的。

在Android8.0之前,是通过 ActivityManagerNative.getDefaul()来获取AMS的代理对象的,现在这个逻辑放到了 ActivityManager中而不是 ActivityManagerNative中,在我之前做的笔记《Android艺术探索》这本书里面,用的是7.0的代码,可以看下面:

在这里插入图片描述

我们来看看getServcie的代码:

// AcitvityManager.java

public static IActivityManager getService() {

return IActivityManagerSingleton.get();

}

这个方法返回一个IActivityManager的对选哪个,有了解AIDL或代理模式的应该就能立马知道 IActivityManagerActivityManagerService在客户端的代理类!

我们来看看 IActivityManagerSingletonget()

// ActivityManager.java

private static final Singleton IActivityManagerSingleton =

new Singleton() {

@Override

protected IActivityManager create() {

//1

final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);

//2

final IActivityManager am = IActivityManager.Stub.asInterface(b);

return am;

}

};

注释1:从 ServiceManager得到一个IBinder,也就是 “IBinder类型的AMS”

注释2:将IBinder通过 asInterface()转换成一个 IActivityManager对象,通过get()可以得到这个对象。

上面是 AIDL的做法,用 进程间通信完成的从 客户端层到 服务端层的实现。8.0之前并不是AIDL的做法。至于AIDL的用法、原理网上已经有n多的blog去学习了。这里不再赘述。

至此,第一阶段结束,execStartActivity方法最终会调用到 ActivityManagerService.startActivity()

这部分其实特别好理解。

2.AMS到ApplicationThread的调用过程

=======================================================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值