源碼解讀-APP啟動(dòng)流程和UI繪制流程

前言:
在Java中,程序的入口是main函數(shù),那么在Android中,程序的入口是在哪里呢?一個(gè)APP啟動(dòng)的過(guò)程又是怎樣的呢? setContentView()加載的布局,是如何添加到窗口中的,如何顯示到屏幕上的? 帶著這些疑問(wèn),我們來(lái)跟著Android系統(tǒng)的源碼,一步一步分析!

注: 分析采用的API 23,看源碼的時(shí)候?qū)uild.gradle中的compileSdkVersion 指定為23,如果找不到ActivityThread等類,說(shuō)明sdk中的api是隱藏的,需要更換Android.jar,GitHub上有去掉 /** @hide */的版本,導(dǎo)入即可!

一:APP的啟動(dòng)流程
啟動(dòng)的入口類:ActivityThread
啟動(dòng)的流程:http://www.cloudchou.com/android/post-788.html
參考博客: https://blog.csdn.net/melodev/article/details/51959347

ActivityThread:
    成員變量:

    內(nèi)部類:
        ApplicationThread

    入口函數(shù):main
        1. 初始化主線程Looper:
            Looper.prepareMainLooper();
            Looper.loop();
        2. 創(chuàng)建ActivityThread:
            ActivityThread thread = new ActivityThread();
            thread.attach(false);//在這個(gè)方法中,將ApplicationThread 和AMS綁定,后續(xù)由AMS調(diào)用ApplicationThread的方法
        3. 給主線程handler賦值
            sMainThreadHandler = thread.getHandler();//return mH;  mH = new H(); private class H extends Handler

ApplicationThread:
    1. 此類有很多scheduleXXX方法,由AMS調(diào)用,如:scheduleLaunchActivity()
    2. 分析:scheduleLaunchActivity()
        最后調(diào)用:sendMessage(H.LAUNCH_ACTIVITY, r); -> mH.sendMessage(msg); //消息機(jī)制
    3. 分析mH -> handleMessage():
        case LAUNCH_ACTIVITY: -> handleLaunchActivity() -> performLaunchActivity() -> activity = mInstrumentation.newActivity();//創(chuàng)建出activity
        繼續(xù)往下看:  callActivityOnCreate(),//看到熟悉的OnCreate()啦

二:UI繪制流程

分析:setContentView() ->  getWindow().setContentView()
        Window:抽象類  -> 僅有的一個(gè)實(shí)現(xiàn)類 PhoneWinodw

PhoneWindow  -> setContentView():
    1. installDecor() : //加載布局容器,加載基礎(chǔ)布局
        generateDecor();    ->new DecorView()
        mContentParent = generateLayout(mDecor);    ->requestFeature()://   requestFeature()方法判斷是否設(shè)置了布局(拋異常),這也是為什么requestFeature()必須在setContentView()之前調(diào)用的原因

        generateLayout():會(huì)根據(jù)不會(huì)的主題,加載不同的布局,如:layoutResource = R.layout.screen_simple;
        打開(kāi)這個(gè)布局文件,會(huì)看到是一個(gè)線性布局,ViewStub,id為action_mode_bar_stub,這是狀態(tài)欄,還有一個(gè)id為content的FrameLayout
        我們自己添加的布局,就是添加到這個(gè)幀布局下;
        概念:
            -> DecorView(繼承FrameLayout)   頂層view
            -> mContentParent(是一個(gè)ViewGroup)

    2. 加載我們自己的布局:mLayoutInflater.inflate(layoutResID, mContentParent); // xml解析

scheduleResumeActivity():setContentView()執(zhí)行完畢,onCreate()執(zhí)行完畢,接下來(lái)AMS調(diào)用 scheduleResumeActivity(),發(fā)消息:
    RESUME_ACTIVITY: 
        -> handleResumeActivity()
                performResumeActivity()://不看這個(gè)
                wm.addView(decor, l);// ViewManager wm  實(shí)現(xiàn)類:WindowManager 還是一個(gè)接口,找到實(shí)現(xiàn)類:WindowManagerImpl
                mGlobal.addView(view, params, mDisplay, mParentWindow);// mGlobal
                root.setView(view, wparams, panelParentView);//調(diào)用了ViewRootImpl的setView()
                requestLayout();//ViewRootImpl的requestLayout()
                scheduleTraversals();
                mTraversalRunnable  //Runnable子類 -> run() ->doTraversal(); ->performTraversals(); ->進(jìn)入view的繪制流程

繪制流程: performTraversals()分析:(traversal 意思是遍歷)
    measureHierarchy():
        performMeasure():最后調(diào)用了 mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        performLayout(): -> 會(huì)遍歷所有子控件,執(zhí)行view.requestLayout(); ->view.layout()
        performDraw(); -> draw(fullRedrawNeeded); -> view.draw()

分析完成后,可以回答以下問(wèn)題:

  1. 為什么requestWindowFeature(Window.FEATURE_NO_TITLE);這行代碼必須在setContentView()之前調(diào)用?

  2. 為什么在onCreate()方法中,我們調(diào)用view.getWidth()等方法,獲取不到view的寬高信息?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剥险,一起剝皮案震驚了整個(gè)濱河市砾赔,隨后出現(xiàn)的幾起案子癣猾,更是在濱河造成了極大的恐慌输吏,老刑警劉巖晚唇,帶你破解...
    沈念sama閱讀 211,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗅战,死亡現(xiàn)場(chǎng)離奇詭異闻牡,居然都是意外死亡净赴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門罩润,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)玖翅,“玉大人,你說(shuō)我怎么就攤上這事割以〗鸲龋” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 157,435評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵严沥,是天一觀的道長(zhǎng)猜极。 經(jīng)常有香客問(wèn)我,道長(zhǎng)消玄,這世上最難降的妖魔是什么跟伏? 我笑而不...
    開(kāi)封第一講書人閱讀 56,509評(píng)論 1 284
  • 正文 為了忘掉前任丢胚,我火速辦了婚禮,結(jié)果婚禮上酬姆,老公的妹妹穿的比我還像新娘嗜桌。我一直安慰自己,他們只是感情好辞色,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布骨宠。 她就那樣靜靜地躺著,像睡著了一般相满。 火紅的嫁衣襯著肌膚如雪层亿。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,837評(píng)論 1 290
  • 那天立美,我揣著相機(jī)與錄音匿又,去河邊找鬼。 笑死建蹄,一個(gè)胖子當(dāng)著我的面吹牛碌更,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洞慎,決...
    沈念sama閱讀 38,987評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼痛单,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了劲腿?” 一聲冷哼從身側(cè)響起旭绒,我...
    開(kāi)封第一講書人閱讀 37,730評(píng)論 0 267
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎焦人,沒(méi)想到半個(gè)月后挥吵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡花椭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評(píng)論 2 327
  • 正文 我和宋清朗相戀三年忽匈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矿辽。...
    茶點(diǎn)故事閱讀 38,664評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡脉幢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗦锐,到底是詐尸還是另有隱情嫌松,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評(píng)論 4 330
  • 正文 年R本政府宣布奕污,位于F島的核電站萎羔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏碳默。R本人自食惡果不足惜贾陷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評(píng)論 3 313
  • 文/蒙蒙 一缘眶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧髓废,春花似錦巷懈、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,764評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至冈爹,卻和暖如春涌攻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背频伤。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,997評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工恳谎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人憋肖。 一個(gè)月前我還...
    沈念sama閱讀 46,389評(píng)論 2 360
  • 正文 我出身青樓因痛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親岸更。 傳聞我的和親對(duì)象是個(gè)殘疾皇子婚肆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評(píng)論 2 349

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