概述
Activity作为Android的四大组件之一,Android主要的界面组成部分,用于直接跟用户进行交互操作,在面试中与Activity相关的知识也是经常被问到,如果你面试的高级岗位,那么对Activity的启动和绘制流程就必须的熟悉,本文将从Activity的启动流程来分析Activity。启动Activity的方式大致有两种:一种是在桌面点击应用程序的图标,进入应用程序的主界面;另一种是在应用程序中,进入一个新的Activity。前者属于launcher启动的范畴,本文不做具体的深入分析,后面会具体的分析,不过它的实质是从一个应用的Activity进入另一个应用Activity。
因此,不管是从桌面进入应用主界面,还是在应用里进入一个新的Activity,最终都会调用Activity$startActivity方法。
值得注意的是,Android 5.0,7.0等版本中启动Activity的流程略微有一些细小的改变,但这并不妨碍我们理解Activity的启动流程。
Binder机制
首先,我们要介绍下Android系统中一个重要的内容:Binder机制。为了满足进程间的通信,Android系统将进程分为了用户(Zygote)进程和系统(SystemServer)进程以及各种应用进程等,为了能够实现各种进程之间的通讯,Android系统采用了自己的进程间通讯方式Binder机制。其中主要涉及到了四种角色:Binder Client,Binder Server,Binder Manager, Binder driver。各种角色之间的关系可以参考下面这张图的介绍:
启动Activity流程解读
当我们使用startActivity() 启动另一个Activity后,主要会调用以下的一些函数。
MyActivity.startActivity() Activity.startActivity() Activity.startActivityForResult Instrumentation.execStartActivty ActivityManagerNative.getDefault().startActivityAsUser() |
首先,我们来看一下startActivity()函数的源码:
@Override public void startActivity(Intent intent) { this.startActivity(intent, null); } @Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { startActivityForResult(intent, -1); } } |
其实,startActivity还有几个其他重载的方法,但是最终都会执行到Activity$startActivityForResult方法。如果是调用startActivity(intent)启动Activity,那么requestCode参数则传入-1,表示需要返回Activity的数据。
到此继续往下看,startActivityForResult方法的具体实现如下:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } } |
在上面的代码中,mParent进行了一个判Null操作,可以发现由于我们是第一次启动Activity,所以这里的mParent为空,所以会执行if分之,然后调用mInstrumentation.execStartActivity方法,并且这里需要注意的是,有一个判断逻辑。即:
if (requestCode >= 0) { mStartedActivity = true; } |
前面说过,调用startActivityForResult的时候只有requestCode的值大于等于0,onActivityResult才会被回调。
Instrumentation
然后我们看一下mInstrumentation.execStartActivity方法的具体实现。在看execStartActivity方法之前,首先看一下Instrumentation,Instrumentation是android系统中启动Activity的一个实际操作类,也就是说Activity在应用进程端的启动实际上就是Instrumentation执行的。那为什么是这样呢?实际上acitivty的启动分为应用进程端的启动和SystemServer服务进程端的启动的,多个应用进程相互配合最终完成了Activity在系统中的启动的,而在应用进程端的启动实际的操作类就是Intrumentation来执行的。
为了方便理解,我们直接看execStartActivity函数源码:
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { result = am.onStartActivity(intent); } if (result != null) { am.mHits++; return result; } else if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; } |
如上,execStartActivity主要有以下几个参数:
this,为启动Activity的对象;
contextThread,为Binder对象,是主进程的context对象;
token,也是一个Binder对象,指向了服务端一个ActivityRecord对象;
target,为启动的Activity;
intent,启动的Intent对象;
requestCode,请求码;
options,参数;
通过,execStartActivity方法可以发现,该方法主要调用ActivityManager.getService()方法,继续查看ActivityManager$getService源码。
/** * @hide */ public static IActivityManager getService() { return IActivityManagerSingleton.get(); } //继续查看 private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } }; //...code } |
可以发现,IActivityManager.Stub.asInterface(b),那么继续看asInterface方法的实现:
static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ActivityManagerProxy(obj); } |
asInterface()返回一个ActivityManagerProxy对象,ActivityManagerProxy继承与IActivityManager,到了这里就引出了我们android系统中很重要的一个概念:Binder机制。
IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE)
如上,是获取一个关联了系统服务ActivityManagerService的Binder对象。所以,IBinder最终和ActivityManagerService形成了绑定关系。
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { } |
所以,ActivityManager.getService().startActivity(…)的最终调用的是ActivityManagerService的startActivity方法。
ActivityManagerService启动Activity
首先来看一下,ActivityManagerService$startActivity的相关源码。
@Override public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId()); } |
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。