以下源码采用API19)
Activity的启动是受AMS(ActivityMessageService),但是直观来讲,很多童鞋并不熟悉AMS,反而对ActivityThread更加熟悉;其实我们的android系统很像一个BS的架构,Liunx驱动以及底层是服务端,应用层是客户端;服务端和客户端通过Binder来通信;
今天我先讲讲客户端,从ActivityThread讲起,当然ActivityThread其实是在AMS通过反射调用加载到虚拟机中的,这篇先不讲,先将ActivityThread启动后和AMS进行交互的过程。
ActivityThread通过它的内部类ApplicationThread,它其实是个BInder,与Ams交互,接受Ams的指令;
ActivityThread启动后,会从mian()函数开始执行,下面我们基本上就分析main函数。
一、为主线程创建一个Looper对象
在main函数中,会调用prepareMainLooper()为UI线程创建一个Looper对象,实际上prepareMainLooper函数是调用prepare(boolean quitAllowed)函数来为当前线程创建Lopper对象的。这里可以进入Looper去看看源码。
在prepare()函数中,会new一个Looper对象,通过ThreadLocalde的set()方法将新创建的Looper对象保存进去,然后可以通过ThreadLocal的get方法来获取当前线程的Looper对象,比如prepareMainLooper中的,sMainLooper = myLooper();实际上myLooper()方法中是通过sThreadLocal.get()来获取当前线程的looper对象的;
前面说了在sThreadLocal.set(new Looper(quitAllowed))的时候会创建一个Looper对象,在创建Looper对象的时候,会初始化一个MessageQueue对象。Looper对象到这里初始化完毕,但是并未进入消息循环,直到下面调用Looper.loop();
源码:
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>"); //(1)为主线程创建一个Looper对象 Looper.prepareMainLooper(); //(2)创建ActivityThread对象 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"); }
/** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */ public static Looper myLooper() { return sThreadLocal.get(); }
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
Looper的构造函数,初始化Looper的时候会创建MessageQueue,和获取当前的线程对象;
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
ThreadLocal:可以看源码中的解释,其实的功能很特殊,可以是不同的线程持有同一个对象,但是不同的线程中该对象具有不同的属性值,比如 有ThreadA,ThreadB,ThreadC共同持有 int objectA;在ABC三个线程中分别赋值:1,2,3,那么会有这种的现象,虽然是同一个引用,但是三个线程中的值各不相同,并且三个线程修改的值也只有在自己的线程才会有效
/** * Implements a thread-local storage, that is, a variable for which each thread * has its own value. All threads share the same {@code ThreadLocal} object, * but each sees a different value when accessing it, and changes made by one * thread do not affect the other threads. The implementation supports * {@code null} values. * * @see java.lang.Thread * @author Bob Lee */ public class ThreadLocal<T> {
二、创建ActivityThread对象
上面讲完了Looper.prepareMainLooper();接下会创建一个ActivityThread对象
见上面源码(2),
ActivityThread thread = new ActivityThread(); thread.attach(false);
这里主要看attach(false)函数,下面是它的源码,
private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { ensureJitEnabled(); } }); android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } // Watch for getting close to heap limit. BinderInternal.addGcWatcher(new Runnable() { @Override public void run() { if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + " total=" + (runtime.totalMemory()/1024) + " used=" + (dalvikUsed/1024)); mSomeActivitiesChanged = false; try { mgr.releaseSomeActivities(mAppThread); } catch (RemoteException e) { } } } }); } else { // Don't set application object here -- if the system crashes, // we can't display an alert, we just want to die die die. android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId()); try { mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); mInitialApplication = context.mPackageInfo.makeApplication(true, null); mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate Application():" + e.toString(), e); } } // add dropbox logging to libcore DropBox.setReporter(new DropBoxReporter()); ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { @Override public void onConfigurationChanged(Configuration newConfig) { synchronized (mResourcesManager) { // We need to apply this change to the resources // immediately, because upon returning the view // hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) { // This actually changed the resources! Tell // everyone about it. if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(newConfig)) { mPendingConfiguration = newConfig; sendMessage(H.CONFIGURATION_CHANGED, newConfig); } } } } @Override public void onLowMemory() { } @Override public void onTrimMemory(int level) { } }); }
因为attach()中传入的是false,那我们就先看if语句中的代码: 注意这一句:
final IActivityManager mgr = ActivityManagerNative.getDefault();
mgr.attachApplication(mAppThread);
其中mAppThread在ActivityThread作为成员变量,在定义的时候便直接初始化了
final ApplicationThread mAppThread = new ApplicationThread();
mgr对象实际上就是ActivityManager的实例,是用来管理Activity的,这里就涉及到ipc调用,和native相关,中代码中的ActivityManagerNative这个名字就能看出来,然后通过attachApplication()将mAppThread和ActivityMananger关联起来,这样系统就能通过持有ApplicationThread的实例来管理每一个Activity的生命周期了,为什么这么说,这里就要ApplicationThread是什么了,它是ActivityThread的一个内部类,见下面源码,我们很清楚的通过下面个函数名称看出来都是做什么用的,很容易的能够看懂是Activity和Service的生命周期的相关的,基本上大部分函数都会调用sendMessage()来发送一个消息,调用Activity或者Service的生命周期:
private class ApplicationThread extends ApplicationThreadNative { private static final String ONE_COUNT_COLUMN = "%21s %8d"; private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d"; private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s"; private int mLastProcessState = -1; private void updatePendingConfiguration(Configuration config) { synchronized (mResourcesManager) { if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(config)) { mPendingConfiguration = config; } } } public final void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) { sendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, token, (userLeaving ? 1 : 0) | (dontReport ? 2 : 0), configChanges); } public final void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) { sendMessage( showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE, token, 0, configChanges); } public final void scheduleWindowVisibility(IBinder token, boolean showWindow) { sendMessage( showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW, token); } public final void scheduleSleeping(IBinder token, boolean sleeping) { sendMessage(H.SLEEPING, token, sleeping ? 1 : 0); } public final void scheduleResumeActivity(IBinder token, int processState, boolean isForward, Bundle resumeArgs) { updateProcessState(processState, false); sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0); } public final void scheduleSendResult(IBinder token, List<ResultInfo> results) { ResultData res = new ResultData(); res.token = token; res.results = results; sendMessage(H.SEND_RESULT, res); } // we use token to identify this activity without having to send the // activity itself back to the activity manager. (matters more with ipc) public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) { updateProcessState(procState, false); ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent; r.referrer = referrer; r.voiceInteractor = voiceInteractor; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; r.persistentState = persistentState; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profilerInfo = profilerInfo; updatePendingConfiguration(curConfig); sendMessage(H.LAUNCH_ACTIVITY, r); } public final void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed, Configuration config) { requestRelaunchActivity(token, pendingResults, pendingNewIntents, configChanges, notResumed, config, true); } public final void scheduleNewIntent(List<ReferrerIntent> intents, IBinder token) { NewIntentData data = new NewIntentData(); data.intents = intents; data.token = token; sendMessage(H.NEW_INTENT, data); } public final void scheduleDestroyActivity(IBinder token, boolean finishing, int configChanges) { sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0, configChanges); } public final void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser, int processState) { updateProcessState(processState, false); ReceiverData r = new ReceiverData(intent, resultCode, data, extras, sync, false, mAppThread.asBinder(), sendingUser); r.info = info; r.compatInfo = compatInfo; sendMessage(H.RECEIVER, r); } ... ... public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); } public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false); BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; if (DEBUG_SERVICE) Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid=" + Binder.getCallingUid() + " pid=" + Binder.getCallingPid()); sendMessage(H.BIND_SERVICE, s); } public final void scheduleUnbindService(IBinder token, Intent intent) { BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; sendMessage(H.UNBIND_SERVICE, s); } public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, int flags ,Intent args) { ServiceArgsData s = new ServiceArgsData(); s.token = token; s.taskRemoved = taskRemoved; s.startId = startId; s.flags = flags; s.args = args; sendMessage(H.SERVICE_ARGS, s); } ... ...省略,自行查看源码 }
3)sendMessage()
其实有4个sendMessage的重载,最后都会调用到,下面这段
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj); Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg); }
这提通过Message.obtain()来获取一个message,见源码,实际上是从消息池中获取一个空闲的Message实例
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); }
然后通过mH.sendMessage来发送消息,
那mH是什么?看到这里很疑问,我们先看看声明:
final H mH = new H();
似乎有些蒙圈,接着看,H实际上是ActivityThread的内部类,是一个继承Handler的子类,专门用来处理ActivityThread的消息的,里面声明了很多消息处理码,通过handleMessage(Message msg),它会根据消息处理码来分发消息处理,比如启动一个Activity,stop一个Activity等等,感兴趣的可以查看源码。
这样就把ActivityThread就通过attach方法将自己的内部类ApplicationThread和ActivityManager关联起来了,ActivityManager持有ActivityThread的引用,便可以发送消息给ActivityThread,来启动和调用Activity或者Service;
ApplicatiiionThread(实际上是一个Binder)对象,Binder会负责接收远程Ams的IPC调用,接受调用后,通过Handler对象的子类H把消息发送给消息列队(MessageQueue),UI线程会从消息列队中取出消息,并执行相应的操作,比如start、stop、pause等。
4)attach函数中的else代码块(这里是系统自动调用的)
mInstrumentation = new Instrumentation();
下面初始化Application,先要创建一个上下文对象Context,然后创建Application对象,并调用onCreate,初始化Application,这里我们的app便启动了。
ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
5)UI主线程接着会调用Looper.loop()方法进入消息循环,处理AMS发送过来的消息;
UI主线程接着会调用Looper.loop()方法进入消息循环体,然后不断地从MessageQueue中读取并处理消息(如果没有消息了,就会进入阻塞状态,知道有新消息被send进来)。
6)Activity的初始化和启动
ActivityThread在接受Ams发送的start某个Activity后,其scheduleLaunchActivity()会被调用,在这个函数中会初始化一些相应的参数,最后通过sendMessage(H.LAUNCH_ACTIVITY, r);来发送消息启动一个Activity;这时候看源码,就是在H类的handleMessage(Message msg)函数中处理的,看switch/case中的第一个case就是LANUCH_ACTIVITY
case LAUNCH_ACTIVITY: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart"); final ActivityClientRecord r = (ActivityClientRecord) msg.obj; r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); handleLaunchActivity(r, null); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break;
再看源码handleLaunchActivity,里面会准备一个启动的Activity的实例a对象,a是通过performLaunchActivity函数创建的,这段源码我就不贴出来了,自己去看。这个函数中会根据ActivityClientRecord中的相关信息创建出一个Activity的实例,下面只截取该函数中Activity的创建代码块
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... ... Activity a = performLaunchActivity(r, customIntent); ... ... }
Activity的创建,根据类名通过ClassLoader加载进来
Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(); if (r.state != null) { r.state.setClassLoader(cl); } } catch (Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException( "Unable to instantiate activity " + component + ": " + e.toString(), e); } }
Instrumentation类的newActivity方法
public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Activity)cl.loadClass(className).newInstance(); }
到此我们的Activity便加入到系统了,但是Activity中的View我们还看不到;
7)Activity中View的初始化过程
在通过handleLaunchActivity加载了Activity后,判断a不是null之后,会调用handleResumeActivity(),在这个函数中会初始化View相关的内容,并添加到Window中,
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) {
// If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); ActivityClientRecord r = performResumeActivity(token, clearHide); if (r != null) {
final Activity a = r.activity; ... ...
//注意这里,初始化window,DecorView,并且WindowManager将DecorView添加进ViewManager中
if (r. window == null && !a.mFinished && willBeVisible) { r. window = r. activity.getWindow() ; View decor = r. window .getDecorView() ; decor.setVisibility(View. INVISIBLE) ; ViewManager wm = a.getWindowManager() ; WindowManager.LayoutParams l = r. window.getAttributes() ; a.mDecor = decor ; l. type = WindowManager.LayoutParams. TYPE_BASE_APPLICATION ; l. softInputMode |= forwardBit ; if (a.mVisibleFromClient) { a.mWindowAdded = true; wm.addView(decor , l) ; } // If the window has already been added, but during resume // we started another activity, then don't yet make the // window visible. } else if (!willBeVisible) { if ( localLOGV) Slog.v( TAG , "Launch " + r + " mStartedActivity set") ; r. hideForNow = true; } } ... ...}
从上面的代码我们可以明白,其实我们平时看到的View的真正的根目录是的DecorView,只是我们看不到它,从上面看到是系统把它INVISIBLE了,它实际上是FragmentLayout,一个ViewGroup,我们平时通过setContentView将一个布局文件或者一个view添加到window中实际上也就是添加到DecorView中的
注:
1)ThreadLocal:
/** * Implements a thread-local storage, that is, a variable for which each thread * has its own value. All threads share the same {@code ThreadLocal} object, * but each sees a different value when accessing it, and changes made by one * thread do not affect the other threads. The implementation supports * {@code null} values. * * @see java.lang.Thread * @author Bob Lee */ public class ThreadLocal<T>