2.读Android源码-冷启动时的ActivityThread
1.Android ActivityThread工作原理
======
2.读Android源码-冷启动时的ActivityThread
前言:
应用冷启动时需要创建进程,开启主线程,实例化应用所需组件。
读ActivityThread源码有助于我们了解这个过程中,客户端做的那些事。
冷启动创建应用时,ActivityThread的主要方法:
- main()
-- 1. 开启消息循环
-- 2. 通知ActivityManagerService
-- 3. 添加GCWatcher- handleBindApplication()
-- 1. 创建LoadedApk
-- 2. 创建Instrumentation
-- 3. 创建Application
-- 4. 通过Instrumentation调用Application的onCreate()方法
main()
main方法是一个应用创建的入口,他主要做了3件事
1. 开启消息循环
调用Looper.prepareLoop() Looper.loop(),开启主线程的消息循环,以便于ApplicationThread调用ActivityThread中的生命周期方法。
public static void main(String[] args) { ... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } ... Looper.loop(); }
2. 通知ActivityManagerService
调用ActivityThread.attach()方法,attach()方法在调用了attachApplication()将ApplicationThread这个Binder交给了ActivityManagerService,意味着ActivityManagerService可以通过ApplicationThread控制我们的应用,建立了服务器端对客户端的通信渠道。
private void attach(boolean system){ ... final IActivityManager mgr = ActivityManager.getService(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } ... }
SDK26以后,去除了Native和Proxy,而是直接从ActivityManager(ServiceManager)中获取ActivityManagerService的Binder对象进行通信
3. 添加GCWatcher
在attach()方法中,添加了监听dialvik内存使用情况得监听者GcWatcher,当内存使用超过总容量的3/4,则打印Log进行记录,并且调用ActivityManagerService的releaseSomeActivities()进行内存释放操作,以防止内存溢出导致应用崩溃。
private void attach(boolean system){ ... 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) { throw e.rethrowFromSystemServer(); } } } }); ... }
handleBindApplication()
ActivityManagerService=AMS
handleBindApplication的被调用时机是:
- 通过上面AMS.attachApplication()后,AMS获得了控制应用的Binder对象ApplicationThread。
- AMS进行了一系列操作后(这里先省略),调用了ApplicationThread的bindApplication()
- bindApplication中通过消息机制,sendMessage到ActivityThread,调用了ActivityThread的handleBindApplication()
handleBindApplication是创建用于所需组件的入口,他主要做了4件事:
1. 创建LoadedApk
LoadedApk对象包含应用的所有信息
private void handleBindApplication(AppBindData data){ ... final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, appContext.getClassLoader(), false, true, false); ... }
2. 创建Instrumentation
Instrumentation是应用组件的管家,组件的生命周期方法都需要通过它来调用,是客户端与服务器端通信的最后一步。
private void handleBindApplication(AppBindData data){ ... final ContextImpl instrContext = ContextImpl.createAppContext(this, pi); try { final ClassLoader cl = instrContext.getClassLoader(); mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate instrumentation " + data.instrumentationName + ": " + e.toString(), e); } ... }
3. 创建Application
调用了LoadedApk.makeApplication()进行Application的创建
private void handleBindApplication(AppBindData data){ ... app = data.info.makeApplication(data.restrictedBackupMode, null); ... }
- 先通过ContextImpl.createAppContext()获得Application的Context
- 再通过Instrumentation.newApplication(),用ClassLoder创建Applicaition
- 创建后Applicaition调用自身的attach(Context)方法,将Context与Applicaition绑定,完成创建
LoadedApk.class public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { ... Application app = null; ... ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); ... return app; }
4. 通过Instrumentation调用Application的onCreate()方法
private void handleBindApplication(AppBindData data){ ... mInstrumentation.callApplicationOnCreate(app); ... }
更新中...
1.Android ActivityThread工作原理
导读
通过前面的学习(复习)我们知道ActivityThread其实不是一个Thread,而是一个final类型的Java类,并且拥有main(String[] args) 方法。Android原生以Java语言为基础,Java的JVM启动的入口就是main(String[] args)。
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); // Install selective syscall interception AndroidOs.install(); // 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(); // 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(); // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line. // It will be in the format "seq=114" long startSeq = 0; if (args != null) { for (int i = args.length - 1; i >= 0; --i) { if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) { startSeq = Long.parseLong( args[i].substring(PROC_START_SEQ_IDENT.length())); } } } ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq); 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"); }
以上为main方法中的全部代码,我们关注以下几点:
- Looper.prepareMainLooper();
- Looper.loop();
- thread.attach(false, startSeq);
- thread.getHandler();
Looper.prepareMainLooper();
主程序Looper的初始化工作
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } } 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)); } public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
可以看到new Looper的时候传了false
Looper.loop();
1.Looper就是字面意思(轮训器),在loop方法中无限循环的去MessageQueue(消息队列)中读取消息。
- MessageQueue则通过next方法无限循环的进行消息出队,无消息时则会进入睡眠
执行thread.attach(false, startSeq);
通过thread.attach(false, startSeq);把ActivityThread 和主线程进行绑定。