Activity的工作過程

序入口函數(shù)定血,ActivityThread的main()函數(shù)

public static void main(String[] args) {
   //此處省略N行.......
   //創(chuàng)建Lopper,主線程Looper
    Looper.prepareMainLooper();
   //創(chuàng)建ActivityThread對(duì)象
    ActivityThread thread = new ActivityThread();
   //false,首次啟動(dòng),需要初始化
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 // 主線程looper,開啟死循環(huán)蝗罗,不斷處理按鍵义图、觸摸等消息减俏,activity的生命周期也由其處理
//若在activity的某個(gè)生命周期執(zhí)行耗時(shí)操作,那么其他的消息無法及時(shí)執(zhí)行碱工,那么整個(gè)loop循環(huán)會(huì)卡頓
//時(shí)間一長(zhǎng)娃承,就會(huì)觸發(fā)拋出ANR
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");

attach()分析

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
   //main入口傳入的fasle
    if (!system) {
     //先走該分支代碼
    //先獲取ActivityManagerService對(duì)象,調(diào)用ActivityManagerService的attachApplication()
      final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
           // ======= 展開分析1 ========
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        //此處省略N行代碼
    } else {
        try {
   //Instrumentation類會(huì)在應(yīng)用的任何代碼執(zhí)行前被實(shí)列化怕篷,用來監(jiān)控系統(tǒng)與應(yīng)用的交互
  //另一個(gè)重要作用是提供Android組件單元測(cè)試历筝。
            mInstrumentation = new Instrumentation();
          //應(yīng)用進(jìn)程conext創(chuàng)建 ====== 展開分析2 =======
            ContextImpl context = ContextImpl.createAppContext(
                    this, getSystemContext().mPackageInfo);
、       //創(chuàng)建mInitialApplication ===== 展開分析3 ========
            mInitialApplication = context.mPackageInfo.makeApplication(true, null);
            mInitialApplication.onCreate();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Unable to instantiate Application():" + e.toString(), e);
        }
    }
    DropBox.setReporter(new DropBoxReporter());
    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            synchronized (mResourcesManager) {
               //立即將此更改應(yīng)用于資源廊谓,因?yàn)樵诜祷貢r(shí)梳猪,將查看視圖層次結(jié)構(gòu)。
                if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());
                    //資源被更改蒸痹,發(fā)送消息通知
                    if (mPendingConfiguration == null ||
                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                        mPendingConfiguration = newConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                    }
                }
            }
        }
        @Override
        public void onLowMemory() {
        }
        @Override
        public void onTrimMemory(int level) {
        }
    });

====展開分析1 ======

ActivityManagerNative春弥,抽象類,一個(gè)Binder通信類
檢索系統(tǒng)的默認(rèn)/全局活動(dòng)管理器叠荠。

static public IActivityManager getDefault() {
   //這里返回的是ActivityManagerService匿沛,繼承自ActivityManagerService
    return gDefault.get();
}

最終調(diào)用ActivityManagerService內(nèi)的attachAppliocation()

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

進(jìn)入attachAoolicationLockede()

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        boolean didSomething = false;
     //遍歷activity棧,找到棧頂?shù)腁ctivity
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFrontStack(stack)) {
                    continue;
                }
               //解鎖
                ActivityRecord hr = stack.topRunningActivityLocked(null);
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                         //找到符合條件的Activity榛鼎,真正啟動(dòng)Activity
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                          //此處省略N行......
                        }
                    }
                }
            }
        }
        //此處省略N行......
        return didSomething;
    }

realStartActivityLocked()內(nèi)調(diào)用了ActivityThread的scheduleLaunchActivity()
此處給Activity賦值了各種信息逃呼,如token,在Android的Window機(jī)制中借帘,添加Dailog蜘渣、View會(huì)校驗(yàn)token,因此這邊也會(huì)將token信息攜帶下去肺然。
(如:"Unable to add window -- token " + attrs.token + " is not valid; is your activity running?這類token異常蔫缸。關(guān)于這塊可以去了解一下窗口機(jī)制)
此段代碼最重要的是最后面的sendMessage。這里發(fā)送了一個(gè)消息际起,交給一個(gè)名為H的handler處理拾碌。H這個(gè)handler幾乎處理所有Activity的生命周期的方法。

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                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;
            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);
    //發(fā)送啟動(dòng)Activity的消息街望,使用內(nèi)部繼承Handelr的H校翔,在ActivityThread創(chuàng)建時(shí)初始化
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

來看一下H的處理
handleMessage內(nèi)調(diào)用handleLaunchActivity()

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, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } bre
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        unscheduleGcIdler();
    //此處省略N行.........
           //初始化WindowManagerGlobal
        WindowManagerGlobal.initialize();
     // ========  performLaunchActivity()內(nèi)部    ============
        //1.加載Activity的class類,執(zhí)行其attach()
       //2.調(diào)用mInstrumentation.callActivityOnCreate灾前,最終調(diào)用Activity的onCreate()
       //3.調(diào)用Activity的start()方法
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
   // =========  handleResumeActivity()內(nèi)部      ==============
    //1.獲取window防症,創(chuàng)建DecorView對(duì)象
    //2.獲取windowManager,將DecorView添加到wm,此時(shí)開啟view的測(cè)量蔫敲,布局饲嗽,繪制等等
   //3.使Activity可見
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
            if (!r.activity.mFinished && r.startsNotResumed) {
                performPauseActivityIfNeeded(r, reason);
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

====展開分析2 ======
ContextImpl(繼承自Context)的構(gòu)造方法,所以返回的是Context
簡(jiǎn)要看下一源碼奈嘿,針對(duì)Context的分析貌虾,后續(xù)會(huì)展開一篇文章,有興趣的話裙犹,可以關(guān)注我~~

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    return new ContextImpl(null, mainThread,
            packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
}
private ContextImpl(ContextImpl container, ActivityThread mainThread,
        LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
        Display display, Configuration overrideConfiguration, int createDisplayWithId) {
    mOuterContext = this;
  //如果創(chuàng)建者沒有指定使用哪個(gè)存儲(chǔ)尽狠,則使用默認(rèn)的應(yīng)用程序位置。
    if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
            | Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
       //此處省略N行代碼
    }
  //傳入ActvityThread
    mMainThread = mainThread;
  //傳入activityToken
    mActivityToken = activityToken;
    mFlags = flags;
    if (user == null) {
        user = Process.myUserHandle();
    }
    mUser = user;
    mPackageInfo = packageInfo;
    //初始化ResourcesManager實(shí)例叶圃,用以獲取資源文件
    mResourcesManager = ResourcesManager.getInstance();
   ///此處省略N行代碼...........
}

======展開分析3 =========
LoadApk類,調(diào)用makeApplication()入?yún)ⅲ╰rue袄膏,null)。

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
     //此處省略N行............
    try {
        java.lang.ClassLoader cl = getClassLoader();
     //此處省略N行............
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
       //通過mInstrumentation創(chuàng)建Application  
      // 
======= 展開分析4  =========
       app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
       //此處省略N行............
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;
    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
           //此處省略N行............
    }
  //此處省略N行............
    return app;
}

=======展開分析4=======

Instrumetation類掺冠,創(chuàng)建Application哩陕,調(diào)用attach(context)
public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class<?> clazz, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    Application app = (Application)clazz.newInstance();
    app.attach(context);
    return app;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赫舒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌闽瓢,老刑警劉巖接癌,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異扣讼,居然都是意外死亡缺猛,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門椭符,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荔燎,“玉大人,你說我怎么就攤上這事销钝∮凶桑” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵蒸健,是天一觀的道長(zhǎng)座享。 經(jīng)常有香客問我,道長(zhǎng)似忧,這世上最難降的妖魔是什么渣叛? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮盯捌,結(jié)果婚禮上淳衙,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好箫攀,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布肠牲。 她就那樣靜靜地躺著,像睡著了一般匠童。 火紅的嫁衣襯著肌膚如雪埂材。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天汤求,我揣著相機(jī)與錄音俏险,去河邊找鬼。 笑死扬绪,一個(gè)胖子當(dāng)著我的面吹牛竖独,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挤牛,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼莹痢,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了墓赴?” 一聲冷哼從身側(cè)響起竞膳,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诫硕,沒想到半個(gè)月后坦辟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡章办,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年锉走,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片藕届。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挪蹭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出休偶,到底是詐尸還是另有隱情梁厉,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布踏兜,位于F島的核電站懂算,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏庇麦。R本人自食惡果不足惜计技,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望山橄。 院中可真熱鬧垮媒,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至它抱,卻和暖如春秕豫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背观蓄。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工混移, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人侮穿。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓歌径,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親亲茅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子回铛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

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