android Activity启动过程 简析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/alcoholdi/article/details/54025327


概括

先简略概括一下Activity的启动过程,以下拿点击Launcher来说。

1.开始请求执行Activity,Launcher进程发送命令到AMS

Launcher就是一个App,点击Launcher会隐式启动一个新的应用。所以跑的也是Activity.startActivity的流程。

接着就是Activity.startActivityForResult()  ——> Instrumentation.execStartActivity()...一系列方法。


2.AMS执行Launcher(栈顶Activity)的onPause方法

AMS通过Binder执行Launcher的onPause方法


3.启动Activity所属的应用进程

-从Zygote中fork一个新应用进程出来。里面有负责调度ActivityRecord和Task的代码。

调度Task的算法涉及的判断很多,和当前回退栈,要启动的activity的启动模式,以及taskAffinity属性,启动Activity时设置的intent的flag等诸多要素相关

-之后会执行ActivityThread类的main方法。Activity就在这个ActivityThread实例中运行。



4.执行启动Activity

AMS通过代理,请求启动Activity。ApplicationThread通知主线程执行该请求。然后,ActivityThread执行Activity的启动,并执行它的生命周期方法。

在ApplicationThreaad中,对应AMS管理Activity生命周期的方法都以scheduleXXXActivity,ApplicationThread在Binder线程中,它会向主线程发送消息,ActivityThread的Handler会调用相应的handleXXXActivity方法,然后会执行performXXXActivity方法,最终调用Activity的onXXX方法。


5.AMS执行Launcher(栈顶Activity)的onStop方法

AMS通过Binder执行Launcher的onStop方法






--------------------------分割线--------------------------

前置说明:安卓众多应用来回切换,肯定不是两两应用进行通信能协调好的事,所以需要一个总管家的身份。这里就是我们的AMS。它掌管着所有Activity的生命周期。

已知AMS是运行在SystemServer这个进程上,众多Activity运行在各种应用进程中,那么问题来了...

重点一:众多Activity怎么与AMS通信的

先来两张UML图



一个图是关于ActivityManager,一个是关于ApplicationThread。

拿ActivityManager这个UML图来分析一下。ApplicationThread跟这个差不多。

我们知道用android实现IPC,写个XXX.aidl,ide会为我们生成一个同文件名不同后缀的XXX.java文件。这个文件里面的结构就像这张UML图的结构。

1.这个XXX.java类首先是一个接口,继承IInterface接口。里面一般声明了需要提供的业务方法。在这里就是IActivityManager。

2.然后XXX.java有一个内部有个抽象类Stub继承Binder实现XXX接口。在这里就是ActivityManagerNative+ActivityManagerProxy。

3.Stub里面还有内部类Proxy实现了XXX接口。在这里就是ActivityManagerProxy。

ActivityManagerNative即Stub相当于服务端。ActivityManagerProxy即Proxy相当于客户端。所以ActivityManager设计成这样的aidl结构完成通信。


再具体一点,来看看这个机制怎么完成startActivity方法。

首先是从Activity.startActivity --> Activity.startActivityForResult() --> Instrumentation.execStartActivity()  

然后就会调用ActivityManagerNative.getDefault().startActivity()方法

getDefault会尝试通过ServiceManager.getService("activity")远程服务的Binder对象,然后进行asInterface转换成IActivityManager,其实返回的就是ActivityManagerProxy。

源码是这个样子的。

先看getDefault部分,使用了自带的Singleton类实现单例模式,并且声明是静态方法。

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
	protected IActivityManager create() {
		IBinder b = ServiceManager.getService("activity");
		if (false) {
			Log.v("ActivityManager", "default service binder = " + b);
		}
		IActivityManager am = asInterface(b);
		if (false) {
			Log.v("ActivityManager", "default service = " + am);
		}
		return am;
	}
};


static public IActivityManager getDefault() {
	return gDefault.get();
}
然后看startActivity部分,类ActivityManagerProxy的startActivity方法

class ActivityManagerProxy implements IActivityManager {
    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }
}
里面是对参数使用Parcel序列化,然后调用transact方法,参数是方法名标识,参数,盛放返回值的容器。

这样就会跳转到ActivityManagerService的onTransact方法,ActivityManagerService会调用父类ActivityManagerNative的onTransact方法。

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        switch (code) {
        case START_ACTIVITY_TRANSACTION:
        {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            String callingPackage = data.readString();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            IBinder resultTo = data.readStrongBinder();
            String resultWho = data.readString();
            int requestCode = data.readInt();
            int startFlags = data.readInt();
            ProfilerInfo profilerInfo = data.readInt() != 0
                    ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
            Bundle options = data.readInt() != 0
                    ? Bundle.CREATOR.createFromParcel(data) : null;
            int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
        }
		}
	}
所以客户端调用的方法都要经过onTransact方法转化。所以里面switch判断一下标识,就进入START_ACTIVITY_TRANSACTION的case里面。里面也有一个startActivity方法(注意此时已经位于AMS进程中了),在ActivityManagerNative这个抽象类里没有实现这个方法,所以交给AMS具体实现的方法来处理了。

所以ActivityManagerNative主要是负责Binder机制中,接受参数,转换处理参数这些功能。之后把参数整理好,才会交个AMS,AMS才是具体的处理业务的逻辑。

之后就是AMS的startActivity方法了,这里面的调用链和处理逻辑就多了。

比如判断这个新进程是不是已经启动了,不需要再从zygote中fork一个进程出来。。。。。。。。。


ps:所以在我脑里,我觉得这两张UML图附上一点业务逻辑,应该是这样。红色部分的是业务逻辑






重点二:ActivityThread的Main方法干了什么

从zygote中fork出一个新进程后,就会执行ActivityThread的main方法。

经典问题,一个App的程序入口到底是什么?回答的就是这个ActivityThread的main方法了

    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        AndroidKeyStoreProvider.install();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
1.这里有关于主线程Looper的操作

我们知道如果主线程像子线程发送消息,需要有Looper.prepare()和Looper.loop()操作。

在这里就是prepareMainLooper(),因为这是主线程,这名字简直不能更形象了。

2.这里有new ActivityThread()。

3.thread.attach(false); 执行ActivityThread的attach方法。看下源码,挑出重点

	private void attach(boolean system) {
		...
        if (!system) {
            ...
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
            ...
    }
里面依旧ActivityManagerNative.getDefault()获取到ActivityManagerProxy。执行attachApplication方法,传的参数mAppThread类型是ApplicationThread。

这个mAppThread是在new ActivityThread()时做为成员变量同时初始化的。

然后中间过程同上面之前说的ActivityManager的binder机制调用流程,这里忽略这些流程,直接看AMS的attachApplication方法。

AMS的attachApplication方法调用attachApplicationLocked方法,里面参数就是当初传过去的ApplicationThread。

接着在这里面又用了这个ApplicationThread调用了bindApplication方法。

public final void bindApplication(String processName, ApplicationInfo appInfo,
		List<ProviderInfo> providers, ComponentName instrumentationName,
		ProfilerInfo profilerInfo, Bundle instrumentationArgs,
		IInstrumentationWatcher instrumentationWatcher,
		IUiAutomationConnection instrumentationUiConnection, int debugMode,
		boolean enableOpenGlTrace, boolean trackAllocation, boolean isRestrictedBackupMode,
		boolean persistent, Configuration config, CompatibilityInfo compatInfo,
		Map<String, IBinder> services, Bundle coreSettings) {

	if (services != null) {
		// Setup the service cache in the ServiceManager
		ServiceManager.initServiceCache(services);
	}

	setCoreSettings(coreSettings);

	AppBindData data = new AppBindData();
	data.processName = processName;
	data.appInfo = appInfo;
	data.providers = providers;
	data.instrumentationName = instrumentationName;
	data.instrumentationArgs = instrumentationArgs;
	data.instrumentationWatcher = instrumentationWatcher;
	data.instrumentationUiAutomationConnection = instrumentationUiConnection;
	data.debugMode = debugMode;
	data.enableOpenGlTrace = enableOpenGlTrace;
	data.trackAllocation = trackAllocation;
	data.restrictedBackupMode = isRestrictedBackupMode;
	data.persistent = persistent;
	data.config = config;
	data.compatInfo = compatInfo;
	data.initProfilerInfo = profilerInfo;
	sendMessage(H.BIND_APPLICATION, data);
}
最后一行看到发消息了,其实发到mH这个Handler里面。

点进去handleMessage方法,能看到很多case,比如LAUNCH_ACTIVITY, PAUSE_ACTIVITY, RESUME_ACTIVITY, DESTROY_ACTIVITY这种跟Activity相关的

还有CREATE_SERVICE, BIND_SERVICE, UNBIND_SERVICE, STOP_SERVICE跟Service相关的。

大概能猜出,这是AMS管理App的一道关卡。

我们找到BIND_APPLICATION标识,看到他进入了handleBindApplication方法里面。

private void handleBindApplication(AppBindData data) {
	...
	if (data.instrumentationName != null) {
		...
			mInstrumentation = (Instrumentation)
				cl.loadClass(data.instrumentationName.getClassName()).newInstance();
		...
	} else {
		mInstrumentation = new Instrumentation();
	}

	...

	try {
		...
		Application app = data.info.makeApplication(data.restrictedBackupMode, null);
		mInitialApplication = app;

		...
		try {
			mInstrumentation.onCreate(data.instrumentationArgs);
		}
		catch (Exception e) {
			throw new RuntimeException(
				"Exception thrown in onCreate() of "
				+ data.instrumentationName + ": " + e.toString(), e);
		}

		try {
			mInstrumentation.callApplicationOnCreate(app);
		} catch (Exception e) {
			if (!mInstrumentation.onException(app, e)) {
				throw new RuntimeException(
					"Unable to create application " + app.getClass().getName()
					+ ": " + e.toString(), e);
			}
		}
	}
	...
}
里面有新建Instrumentation的代码,能理解,Activity的生命周期方法都是Instrumentation调用的,当然要先new一个。


然后是makeApplication这个方法,这名字+返回值是个Application,很容易猜到是创建应用的Application。进去里面一看,果然是这样。

这个创建方法需要在LoadedApk中转一手,需要需要这个类是可以读取到xml里面的自定义Application的类名字符串(入股有自定义Application的话,没有会用默认字符串“android.app.Application”)。
然后根据类的全名用反射newInstance出来一个Application。


最后调用callApplicationOnCreate,里面只有一个代码,就是执行application的onCreate方法。


所以其中一个重要流程是,运行应用Application的相关业务。接下来回到ActivityManagerService的attachApplicationLocked方法中,下一步是mStackSupervisor.attachApplicationLocked(app)。

这个app是ProcessRecord的类型,本来我觉得这是AMS(服务端)保存某一个应用(客户端)信息的实体,心里称它为“应用实体信息类”。后来发现并不能这样想,因为一个进程里面可能有多个应用的Activity,所以还是只能称为“进程实体信息类”。

attachApplicationLocked方法里面会调用realStartActivityLocked方法,里面有一句代码app.thread.scheduleLaunchActivity。这个thread是实际上是ApplicationThreadProxy类的实体,所以这句话会通过binder机制,调用到ApplicationThread里面的scheduleLaunchActivity方法。

在这个方法的后一行看到发送一个LAUNCH_ACTIVITY的消息到H这个Hander里面。找到LAUNCH_ACTIVITY这个case,我们看到执行了handleLaunchActivity方法。


private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	...
	Activity a = performLaunchActivity(r, customIntent);
	...
	if (a != null) {
		...
		handleResumeActivity(r.token, false, r.isForward,
				!r.activity.mFinished && !r.startsNotResumed);
	...	
}

里面有两行重要的代码,重要代码一,执行perforLaunchActivity方法。

   private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
		...
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
         ...
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
        ...
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
		...

        return activity;
    }


里面有一句mInstrumentation.newActivity方法。点进去只有一句代码,功能就是通过反射创建出一个Activity实体。

然后下面会有mInstrumentation.callActivityOnCreate方法。里面的调用链是Activity.performCreate()——>Activity.onCreate()这样就执行了我们熟悉的onCreate方法。

后面又有activity.performStart()。里面的调用链是Instrumentation.callActivityOnStart()——>Activity.onStart()。


然后回到handleLaunchActivity的重要代码二,handleResumeActivity里面的调用链是ActivityThread.performResumeActivity()——>Activity.performResume()——>Instrumentation.callActivityOnResume()——>Activity.onResume().执行了我们熟悉的onResume方法。这样Activity启动的主要流程就跑完了。


总结一下重点二。

首先想讲一下之前一直没搞清ApplicationThread和ActivityThread这两者的区别。这两个名字实在给我造成了很大的误会。

看了源码后,才知道。ActivityThread本质是一个线程,最关键的是它竟然没继承Thread我也是很纳闷!!我们常说的UI线程,主线程就是这货。

ApplicationThread跟Thread没多大关系,它主要是配合ApplicationThreadNative和ApplicationThreadProxy完成Binder进程间通信的。所以为啥元老Android发明者一开始要给定这个名字呢??

然后想讲其实整个ActivityThread的attach方法,里面涉及的代码,所有方法调用链,随便拿出一个来我感觉细聊的话都可以写篇文章。

很多细节比如intent的传递,ActivityThread时候时候会新建进程什么时候会寻找已有进程,activity启动是在具体什么时候读取的xml里面该activity标签的自定义属性的等等,都暂时忽略了。


//TODO

//给上面代码调用画个时序图。。。


猜你喜欢

转载自blog.csdn.net/alcoholdi/article/details/54025327