摘要:最近有好多人問我沒信心去深造了,找不到好的工作,其實我以一個他們進行回復,發現他們主要是內心比較浮躁,要知道技術行業永遠缺少的是高手。至此整體繪制過程我們就已經非常清楚了。我門可以根據這種繪制的流程來操作自己的自定義組件。
最近有好多人問我Android沒信心去深造了,找不到好的工作,其實我以一個他們進行回復,發現他們主要是內心比較浮躁,要知道技術行業永遠缺少的是高手。建議先閱讀淺談Android發展趨勢分析,在工作中,總結菜式王道,沉淀才能成長!
前言在android當中對于UI體系當中往往我們會在繪制UI的時候碰到各種各樣的問題而不知道從何解決, 也有時需要開發更改自定義組件時,需要做自己的調整,或者是實現某個自定義特效時的思路不明確,想要達到去玩轉UI的最為基礎的部分,就是去全面的深入了解UI的繪制流程.所以接下來帶大家去進行全面分析UI整體的繪制體系.
思路:android程序啟動--->Activity加載并完成生命周期--->setContentView--->圖形繪制
疑惑:1.Android程序是如何啟動,Activity生命周期如何調用?
2.在Activity onCreate當中我們的setContentView是如何將UI文件加載?
3.UI是如何繪制的?答案:
眾所周知,我們的java程序想要開啟需要依賴于main方法,也就是我們的程序入口(主線程)進入,但是在我們日常開發android程序的過程當中我們并沒有發現main方法的存在,那么android當中的是如何開始運行的?
熟悉的朋友們可能都知道在android當中存在一個叫做ActivityThread的類,這個類代表的是android當中的主線程,而在這個類當中我們看到了比較熟悉的main方法,那么現在是否可以認為我們的android在打開app時是首先調用的是當前這個類的main,也就是此處為我們的啟動點
在此處可以看到Activity調用了一個attach()方法
在這里我們可能首先要考慮的是getService拿出來的是什么?
進去之后,我們會發現
在這個當中,里面調用了的系統的ActivityManagerService這個服務,并且給出了一個Binder接口
那么在這里,我們可以聯想到,在android當中的binder通信機制,那么實際上我們的ActivityManager是有系統服務所調用管理,并且通過在binder接口當中進行調用,這也是為什么我們講Activity是跨進程訪問的原因
那么明白了這個時候能夠得到ActivityManager之后,我們接著回到attach當中繼續看下去, 這個時候會發現,我們調用了一個attachApplication方法(見圖2)這個方法又是干嘛的?attachApplication在這里的作用其實實際上是ActivityThread通過attach獲取到,然后將applciationThread將其關聯,把activity相關信息存儲在applciationThread里面,apllicationThread的類為activity的各種狀態做了相對應的準備工作
這個時候我們需要關注,ApplicationThread當中做了什么?
當我們打開ApplicationThread中我們會看到一堆的schedle方法,這些方法的名稱其實就可以給我們表明,代表的是在執行Activity的某種狀態時調用的計劃執行方法
這時我們會看到一個scheduleLaunchActivity方法,表示計劃加載時調用的
這里我門發現了一個很有意思的事情
這個上面我們會看到一個ActivityClientRecord對象,這個對象其實實際上就是我們的Activity
而且似乎每一個方法還干了一件讓我們非常熟悉的一件事, 進行了一次sendMessage()將當前創建的Activity發送了出去
當走到這里我們會發現最終我們調用的是Handler的消息通信機制,也就是說,在這里我們可以總結一下,
當Activity狀態改變時,都會有對應的一個消息發送出去
而接收這里,我能發現通過發送時不同的狀態,這邊調用了不同的handlerXXXActivity方法
在這里,我門貌似發現了Activity的生命周期的調用痕跡,那么其實到此為止,我門可以得出一個結論,
Application運行的過程當中,對于Activity的操作,狀態轉變,其實實際上是通過Handler消息機制來完成的,
Application當中只管去發, 由消息機制負責調用,因為在main方法當中我門的Looper輪訓器是一直在進行輪訓的
而當我們在加載Activity的時候,當中調用了一個performLaunchActivity()方法,在這個中間我發現了我們onCreate的調用痕跡
也就是說,到目前為止我們能夠明白,整個Application加載Activity的整套流程是怎么回事
那么接下來我們需要關注的是,在onCreate當中我們所寫的setContentView到底干了什么
2.setContentView在onCreate當中我們往往會使用setContentView去進行設置我們自己的布局文件或者view,那么在這當中他到底是怎么做的?通過觀察源碼,這個時候通過一系列線索我找到了最終的位置PhoneWindow類
這個時候我們會看到他做了兩個事情,一個是installDecor,另一個是inflate,這兩個后一個不難猜出他是在進行布局文件的解析, 前面的我們認為她是在初始化某個東西
進來之后發現他初始化了兩個東西,一個叫做mDecor,一個叫做mContentParent
我們看到了mDecor是一個DecorView
mContentParent是一個ViewGroup
透過注釋的翻譯,其實我們就能很明確知道這兩個是用來干嘛的
// This is the view in which the window contents are placed. It is either(這是放置窗口內容的視圖)
// mDecor itself, or a child of mDecor where the contents go.(它要么是mDecor本身,要么是mDecor的子類的內容。)
//This is the top-level view of the window, containing the window decor.(這是在窗口當中的頂層View,包含窗口的decor)
一個代表的是頂層view,一個用來裝他下面的視圖內容
在接著往下看的時候,我門發現,generateLayout方法當中,發現了在此處進行了大量的requestFeature的調用,也就是所,我們的requestFeature
然后在下面我門會發現在做了一件事情,
當前這里竟然在加載布局文件,并且生成了一個view, 但是好像貌似不是我門自己的
所以我們需要去探尋他到底加載了一個什么東東?
這是我找到了一個比較有意思的組件,
在這個上面我看到了一句這樣的注釋
//This is an optimized layout for a screen, with the minimum set of features
enabled.
這是一個屏幕的優化布局,具有最小的特征集啟用。
通過注釋和一些資料分析, 得到了一個比較坑的結果。
這是DecorView默認的一個渲染,然后我門自己的布局都是渲染到她的FrameLayout上的
那么在這里我門現在能夠明白,installDector其實實際上是在初始化兩個視圖容器,然后加載系統的R資源及特征,產生了一個基本布局
那么接著回到之前我門關注的另外一個方法mLayoutInflater.inflate(layoutResID, mContentParent);
這個方法就比較好理解了,
這這段注釋上面我門就可以得到一個信息
//Inflate a new view hierarchy from the specified xml resource.(從指定的視圖當中獲取試圖的層次結構,意思就是,現在在加載自己的資源)
而具體流程就不貼代碼了給各位上一張圖
那么在這里我門就能夠明白,setContentView其實做了兩件比較核心的事情,就是加載環境配置,和自己的布局,那么接下來我門需要考慮的事情就是,他到底怎么畫到界面上的
3.UI是如何繪制的?通過前面兩個章節,我門了解到,程序對于activity生命周期的調用,以及我們的視圖資源的由來。這是我門需要找到的是我門的繪制起點在哪?
在ActivityThread啟動時, 我發現在加載handleLaunchActivity方法調用performLaunchActivity方法之后又調用了一個handleResumeActivity在這里我發現了繪制流程的開始
通過前面的流程我門知道,onCreate之行完成之后,所有資源交給WindowManager保管
在這里,將我們的VIew交給了WindowManager,此處調用了addView
進入addView之后我們發現了一段這樣的代碼,他將視圖,和參數還有我門的一個ViewRoot對象都用了容器去裝在了起來,那么在此處我門可以得出,是將所有的相關對象保存起來
mViews保存的是View對象,DecorView
mRoots保存和頂層View關聯的ViewRootImpl對象
mParams保存的是創建頂層View的layout參數。
而WindowManagerGlobal類也負責和WMS通信
而在此時,有一句關鍵代碼root.setView,這里是將我們的參數,和視圖同時交給了ViewRoot,那么這個時候我們來看下ViewRoot當中的setView干了什么
終于在這里讓我發現了讓我明白的一步
在這里我門會看到view.assignParent的設置是this, 那么也就是說在view當中parent其實實際上是ViewRoot
那么在setContentView當中調用了一個setLayoutParams()是調用的ViewRoot的
而在ViewRoot當中發現了setLayoutParams和preformLayout對requestLayout方法的調用
在requestLayout當中發現了對scheduleTraversals方法的調用而scheduleTraversals當中調用了doTraversal的訪問,最終訪問到了performTraversals(),而在這個里面,我發現了整體的繪制流程的調用
當前里面依次是用了
UI繪制先回去測量布局,然后在進行布局的擺放,當所有的布局測量擺放完畢之后,進行繪制。
至此整體UI繪制過程我們就已經非常清楚了。
我門可以根據這種繪制的流程來操作自己的自定義組件。
作者:barry 鏈接:https://www.jianshu.com/p/0b1...,轉載請注明原創
總結對于我們APP開發者來講,建議大家不要以市場行情的變化而受影響,堅持自己喜歡人認定的路線走下去,沉淀和進步!
2018 互聯網IT開發者簡歷如何脫穎而出
最新2017(Android)面試題級答案(精選版)
如果有什么的問題,歡迎隨時來撩我。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71196.html
摘要:一文教你讀懂云計算中的那些專有名詞云計算簡單點講就是把以前需要本地處理器計算的任務交到了互聯網上的服務器去做。在現代云計算當中扮演著至關重要的一環,充當各元素的橋梁的角色。一文教你讀懂云計算中的那些專有名詞云計算(cloud computing)簡單點講就是把以前需要本地處理器計算的任務交到了互聯網上的服務器去做。是基于互聯網的相關服務的增加、使用和交付模式,通常涉及通過互聯網來提供動態易擴...
摘要:在較低水平的神經元中,一個多樣性術語可以揭示一個特征所代表的不同方面簡單優化用多樣性進行的優化揭示了四個不同的彎曲的方面。注意勺子的紋理和顏色與狗的皮毛相似,從而足以讓神經元激活。下面,一個神經元對兩種類型的動物臉部以及車做出響應。 邊緣(層 conv2d0)紋理(層 mixed3a)模式(層 mixed4a)部分(層 mixed4b & mixed4c)目標(層 mixed4d & mix...
摘要:是一個最小的庫,但由于其對尺寸的追求,它的很多代碼可讀性比較差,市面上也很少有全面且詳細介紹的文章,本篇文章希望能幫助你學習的源碼。建議與源碼一起閱讀本文。 作為一名前端,我們需要深入學習react的運行機制,但是react源碼量已經相當龐大,從學習的角度,性價比不高,所以學習一個react mini庫是一個深入學習react的一個不錯的方法。 preact是一個最小的react mi...
摘要:,,面向切面編程。,切點,切面匹配連接點的點,一般與切點表達式相關,就是切面如何切點。例子中,注解就是切點表達式,匹配對應的連接點,通知,指在切面的某個特定的連接點上執行的動作。,織入,將作用在的過程。因為源碼都是英文寫的。 之前《零基礎帶你看Spring源碼——IOC控制反轉》詳細講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動態代理嗎?看這篇就夠了》介紹了下...
閱讀 1438·2023-04-25 16:31
閱讀 2040·2021-11-24 10:33
閱讀 2745·2021-09-23 11:33
閱讀 2528·2021-09-23 11:31
閱讀 2900·2021-09-08 09:45
閱讀 2336·2021-09-06 15:02
閱讀 2647·2019-08-30 14:21
閱讀 2313·2019-08-30 12:56