ActivityThread的一些分析

ActivityThread

翻譯:它管理應(yīng)用程序進(jìn)程中主線程的執(zhí)行,根據(jù)活動(dòng)管理器的請(qǐng)求虫埂,在其上調(diào)度和執(zhí)行活動(dòng)祥山、廣播和其他操作。

ActivityThread是app啟動(dòng)的入口告丢,會(huì)執(zhí)行main方法:

public static void main(String[] args) {
//創(chuàng)建MainLooper
        Looper.prepareMainLooper();
//創(chuàng)建ActivityThread枪蘑,執(zhí)行attach()方法,第一個(gè)參數(shù)代表是否是系統(tǒng)應(yīng)用损谦。
        ActivityThread thread = new ActivityThread();
        
        thread.attach(false, startSeq);
//sMainThreadHandler就是ActivityThread用于處理消息的handle
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
//執(zhí)行 Looper.loop()
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }


創(chuàng)建MainLooper岖免,并儲(chǔ)存到從sThreadLocal中。

Looper-》

//->Looper.prepareMainLooper
  public static void prepareMainLooper() {
  //創(chuàng)建looper照捡,并儲(chǔ)存
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            //獲取looper
            sMainLooper = myLooper();
        }
    }
    //->Looper.prepare
     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.myLooper
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

看下ActivityThread的成員變量:

public final class ActivityThread {
//ApplicationThread是ActivityThread的內(nèi)部類颅湘,其實(shí)現(xiàn)IApplicationThread.Stub的接口
//Binder通信的時(shí)候,他的代理對(duì)象在服務(wù)端栗精,用來(lái)和系統(tǒng)服務(wù)交互闯参,并將服務(wù)端的消息發(fā)送到客戶端,也就是ActivityThread悲立。
   final ApplicationThread mAppThread = new  ApplicationThread();
   //從sThreadLocal.get()到剛才創(chuàng)建的mainLopper對(duì)象
   final Looper mLooper = Looper.myLooper();
   //用于發(fā)送和處理消息的handle 鹿寨,繼承Handle 
   final H mH = new H();
  
}

繼續(xù)看下attach方法:

//上面調(diào)用處傳進(jìn)來(lái)了第一個(gè)參數(shù)是false,表示是否是系統(tǒng)應(yīng)用,第二個(gè)參數(shù)是時(shí)間薪夕。
 private void attach(boolean system, long startSeq) {
     if (!system) {//不是系統(tǒng)應(yīng)用
     //這里創(chuàng)建的mgr就是服務(wù)端ams在客戶端的代理類脚草,主要用于binder通信。
          final IActivityManager mgr = ActivityManager.getService();
          //這里會(huì)創(chuàng)建application原献,并且會(huì)將客戶端的ApplicationThread的對(duì)象傳遞給服務(wù)段馏慨,進(jìn)行一個(gè)綁定,用來(lái)binder通信
           mgr.attachApplication(mAppThread, startSeq);
     }  else {//是系統(tǒng)應(yīng)用
           mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
     }
 }

也就是說(shuō)姑隅,向ams發(fā)送創(chuàng)建Applicaiton的請(qǐng)求和ams綁定客戶端ApplicationThread對(duì)象的操做都在這里面写隶。

繼續(xù)跟進(jìn)看下ActivityManagerService-》attachApplication

public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
      int callingPid = Binder.getCallingPid();
      final long origId = Binder.clearCallingIdentity();
      attachApplicationLocked(thread, callingPid);
      Binder.restoreCallingIdentity(origId);
    }
}

ActivityManagerService-》attachApplicationLocked


private boolean attachApplicationLocked(IApplicationThread thread, int pid) {

    if (app.instr != null) {
      thread.bindApplication(processName, appInfo, providers,
                             app.instr.mClass,
                             profilerInfo, app.instr.mArguments,
                             app.instr.mWatcher,
                             app.instr.mUiAutomationConnection, testMode,
                             mBinderTransactionTrackingEnabled, enableTrackAllocation,
                             isRestrictedBackupMode || !normalMode, app.persistent,
                             new Configuration(getGlobalConfiguration()), app.compat,
                             getCommonServicesLocked(app.isolated),
                             mCoreSettingsObserver.getCoreSettingsLocked(),
                             buildSerial);
    } else {
      thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                             null, null, null, testMode,
                             mBinderTransactionTrackingEnabled, enableTrackAllocation,
                             isRestrictedBackupMode || !normalMode, app.persistent,
                             new Configuration(getGlobalConfiguration()), app.compat,
                             getCommonServicesLocked(app.isolated),
                             mCoreSettingsObserver.getCoreSettingsLocked(),
                             buildSerial);
    }

    return true;
}

很明顯,通過(guò) IApplicationThread 又將代碼回調(diào)到了 Client 端讲仰。

看ApplicationThread-》bindApplication方法:開(kāi)始發(fā)送H.BIND_APPLICATION的消息了慕趴。當(dāng)然接受的地方就是在ActivityThread里面了。

public final void bindApplication(... ...) {
    sendMessage(H.BIND_APPLICATION, data);
}

// 根據(jù)消息機(jī)制,我們?cè)?ActivityThread#H 中尋找消息處理
public void handleMessage(Message msg) {
    case BIND_APPLICATION:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
        AppBindData data = (AppBindData)msg.obj;
        handleBindApplication(data);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;
}

我們先了解下這個(gè)服務(wù)端給我們的AppBindData是個(gè)什么:
首先他也是ActivityThread的內(nèi)部類秩贰,看下的成員都有啥霹俺。


    static final class AppBindData {
         LoadedApk info;//關(guān)于當(dāng)前加載的 .apk 的本地狀態(tài)。
         String processName;//進(jìn)程名稱
         ApplicationInfo appInfo; //檢索有關(guān)特定應(yīng)用程序的信息毒费。這對(duì)應(yīng)于從 AndroidManifest.xml 的<application>標(biāo)記收集的信息丙唧。
         ComponentName instrumentationName;//instrumentation名字,通過(guò)源碼我猜是ams通過(guò)我們的應(yīng)用信息生成的觅玻,然后讓我們按照這個(gè)名稱去創(chuàng)建隊(duì)員的instrumentation想际。因?yàn)榉瓷渖蒊nstrumentation就是按照的這個(gè)名字。
    }

繼續(xù)看下拿這個(gè)AppBindData去干啥了:

ActivityThread-》handleBindApplication

/ 
private void handleBindApplication(AppBindData data) {

    final InstrumentationInfo ii;
    if (data.instrumentationName != null) {
        ii = new ApplicationPackageManager(null, getPackageManager())
          .getInstrumentationInfo(data.instrumentationName, 0);
    } else {
        ii = null;
    }

    // 根據(jù)上層調(diào)用傳入的參數(shù)溪厘,決定初始化 mInstrumentation 實(shí)例的方式
    // 1. 使用 ClassLoader 初始化胡本;
    if (ii != null) {
        final ApplicationInfo instrApp = new ApplicationInfo();
        ii.copyTo(instrApp);
        instrApp.initForUser(UserHandle.myUserId());
        final LoadedApk pi = getPackageInfo(......);
        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
//利用這個(gè)AppBindData的instrumentationName去創(chuàng)建Instrumentation
        try {
          final ClassLoader cl = instrContext.getClassLoader();
          mInstrumentation = (Instrumentation)
            cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        } 

        final ComponentName component = new ComponentName(ii.packageName, ii.name);
        mInstrumentation.init(... ...);
    } else {
    //2. InstrumentationInfo==null,直接 new 對(duì)象
        mInstrumentation = new Instrumentation();
    }
    
    try {
        // 調(diào)用 makeApplication 去創(chuàng)建 Application 對(duì)象,info就是LoadedApk畸悬。
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app; 
        
        // 初始化 application 對(duì)象后侧甫,通過(guò) mInstrumentation 調(diào)用 application 的 onCreate 方法
        mInstrumentation.callApplicationOnCreate(app);
    }
}

創(chuàng)建Application 對(duì)象:

LoadedApk-》makeApplication


public Application makeApplication(boolean forceDefaultAppClass,
                                   Instrumentation instrumentation) {
    if (mApplication != null) {
      return mApplication;
    }

    java.lang.ClassLoader cl = getClassLoader();
    ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    // 入?yún)⒌?instrumentation 為 null,使用 ActivityThread 的 mInstrumentation
    app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    appContext.setOuterContext(app);

    return app;
}

實(shí)際還是在Instrumentation中創(chuàng)建Application蹋宦。

Instrumentation-》newApplication

public Application newApplication(ClassLoader cl, String className, Context context) {
    return newApplication(cl.loadClass(className), context);
}

static public Application newApplication(Class<?> clazz, Context context){
    Application app = (Application)clazz.newInstance();
    app.attach(context);
    return app;
}

接下來(lái)再看一下Activity啟動(dòng)的時(shí)候披粟,ActivityThread做了什么?

當(dāng)我們調(diào)用startActivity的時(shí)候冷冗,最后通過(guò)Instrumentation.execStartActivity()方法守屉,里面會(huì)去獲取ams在客戶端的代理類,跟AMS進(jìn)行Binder通信蒿辙,ams會(huì)去調(diào)用自己的startActivity()方法拇泛,ams處理完成后,通過(guò)在服務(wù)端的ApplicationThread的代理類將啟動(dòng)事件傳遞到ApplicationThread中思灌,ApplicationThread通過(guò)發(fā)送handler消息到ActivityThread俺叭,然后ActivityThread收到消息后處理啟動(dòng)Activity的邏輯。
也就是說(shuō)針對(duì)Activity的相關(guān)的操作泰偿,最后都要到這里去執(zhí)行熄守。

查看==ActivityThread.performLaunchActivity()==:

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        //創(chuàng)建Activity,還是mInstrumentation創(chuàng)建的甜奄。還是發(fā)射柠横。
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
           
        } 
        //執(zhí)行activity的attach方法
          activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);
                        
        //這個(gè)方法會(huì)去執(zhí)行 activity.performCreate(icicle);接著就是activiy的onCreate方法了,參數(shù)是Bundle课兄。
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
               
 }

Activity創(chuàng)建后取執(zhí)行attach方法了牍氛,之后執(zhí)行oncreate方法。我們看下attach方法:

 final void attach(Context context, ActivityThread aThread,
                      Instrumentation instr, IBinder token, int ident,
                      Application application, Intent intent, ActivityInfo info,
                      CharSequence title, Activity parent, String id,
                      NonConfigurationInstances lastNonConfigurationInstances,
                      Configuration config, String referrer, IVoiceInteractor voiceInteractor,
                      Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
                          
       attachBaseContext(context);
       mFragments.attachHost(null /*parent*/);
       mWindow = new PhoneWindow(this, window, activityConfigCallback);              mWindow.getLayoutInflater().setPrivateFactory(this);
       
         mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mAssistToken = assistToken;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        
        mWindow.setWindowManager(
                (WindowManager) context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
                      }

可以看到烟阐,fragment也進(jìn)行attach操作了搬俊,phoneWindow也是這時(shí)候創(chuàng)建的紊扬,window的LayoutInflater也是這時(shí)候創(chuàng)建的,然后將一些參數(shù)進(jìn)行了應(yīng)用賦值唉擂。最后給windon設(shè)置了setWindowManager餐屎。

最后總結(jié)一下,ActivityThread它管理應(yīng)用程序進(jìn)程中主線程的執(zhí)行玩祟,根據(jù)活動(dòng)管理器的請(qǐng)求腹缩,在其上調(diào)度和執(zhí)行活動(dòng)、廣播和其他操作空扎〔厝担~~~~~

最后,睡覺(jué)啪啪啪~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末转锈,一起剝皮案震驚了整個(gè)濱河市盘寡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撮慨,老刑警劉巖竿痰,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異砌溺,居然都是意外死亡影涉,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)抚吠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)常潮,“玉大人弟胀,你說(shuō)我怎么就攤上這事楷力。” “怎么了孵户?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵萧朝,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我夏哭,道長(zhǎng)检柬,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任竖配,我火速辦了婚禮何址,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘进胯。我一直安慰自己用爪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布胁镐。 她就那樣靜靜地躺著偎血,像睡著了一般诸衔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上颇玷,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天笨农,我揣著相機(jī)與錄音,去河邊找鬼帖渠。 笑死谒亦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的空郊。 我是一名探鬼主播诊霹,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼渣淳!你這毒婦竟也來(lái)了脾还?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤入愧,失蹤者是張志新(化名)和其女友劉穎鄙漏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體棺蛛,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怔蚌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旁赊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桦踊。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖终畅,靈堂內(nèi)的尸體忽然破棺而出籍胯,到底是詐尸還是另有隱情,我是刑警寧澤离福,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布杖狼,位于F島的核電站,受9級(jí)特大地震影響妖爷,放射性物質(zhì)發(fā)生泄漏蝶涩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一絮识、第九天 我趴在偏房一處隱蔽的房頂上張望绿聘。 院中可真熱鬧,春花似錦次舌、人聲如沸熄攘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鲜屏。三九已至烹看,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間洛史,已是汗流浹背惯殊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留也殖,地道東北人土思。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像忆嗜,于是被迫代替她去往敵國(guó)和親己儒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容