activityThread之內容分析


 

 

2.讀Android源碼-冷啟動時的ActivityThread

1.Android ActivityThread工作原理

======

2.讀Android源碼-冷啟動時的ActivityThread

 

前言:
應用冷啟動時需要創建進程,開啟主線程,實例化應用所需組件。
讀ActivityThread源碼有助於我們了解這個過程中,客戶端做的那些事。

冷啟動創建應用時,ActivityThread的主要方法:

  1. main()
    -- 1. 開啟消息循環
    -- 2. 通知ActivityManagerService
    -- 3. 添加GCWatcher
  2. 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的被調用時機是:

  1. 通過上面AMS.attachApplication()后,AMS獲得了控制應用的Binder對象ApplicationThread。
  2. AMS進行了一系列操作后(這里先省略),調用了ApplicationThread的bindApplication()
  3. 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(消息隊列)中讀取消息。

  1. MessageQueue則通過next方法無限循環的進行消息出隊,無消息時則會進入睡眠

執行thread.attach(false, startSeq);

通過thread.attach(false, startSeq);把ActivityThread 和主線程進行綁定。

執行thread.getHandler();

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM