用兩張圖告訴你,為什麼你的 App 會卡頓

來源:互聯網
上載者:User

標籤:you   關注   講解   graph   roo   boolean   surf   handle   cal   

Cover
有什麼料?
從這篇文章中你能獲得這些料:

知道setContentView()之後發生了什嗎?
知道Android究竟是如何在螢幕上顯示我們期望的畫面的?
對Android的視圖架構有整體把握。
學會從根源處分析畫面卡頓的原因。
掌握如何編寫一個流暢的App的技巧。
從源碼中學習Android的細想。
收穫兩張自製圖,協助你理解Android的視圖架構。

link
從setContentView()說起
public class AnalyzeViewFrameworkActivity extends Activity {br/>@Override
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_analyze_view_framwork);
}
}
上面這段代碼想必Androider們大都已經不能再熟悉的更多了。但是你知道這樣寫了之後發生什麼了嗎?這個布局到底被添加到哪了?我的天,知識點來了!

可能很多同學也知道這個布局是被放到了一個叫做DecorView的父布局裡,但是我還是要再說一遍。且看??

image

這個圖可能和夥伴們在書上或者網上常見的不太一樣,為什麼不太一樣呢?因為是我自己畫的,哈哈哈...

下面就來看著圖捋一捋Android最基本的視圖架構。

PhoneWindow
估計很多同學都知道,每一個Activity都擁有一個Window對象的執行個體。這個執行個體實際是PhoneWindow類型的。那麼PhoneWindow從名字很容易看出,它應該是Window的兒子(即子類)!

知識點:每一個Activity都有一個PhoneWindow對象。

那麼,PhoneWindow有什麼用呢?它在Activity充當什麼角色呢?下面我就姑且把PhoneWindow等同於Window來稱呼吧。

image
Window從字面看它是一個視窗,意思和PC上的視窗概念有點像。但也不是那麼準確。看圖說。可以看到,我們要顯示的布局是被放到它的屬性mDecor中的,這個mDecor就是DecorView的一個執行個體。下面會專門擼DecorView,現在先把關注點放到Window上。Window還有一個比較重要的屬性mWindowManager,它是WindowManager(這是個介面)的一個實作類別的一個執行個體。我們平時通過getWindowManager()方法獲得的東西就是這個mWindowManager。顧名思義,它是Window的管理者,負責管理著視窗及其中顯示的內容。它的實際實作類別是WindowManagerImpl。可能童鞋們現在正在PhoneWindow中尋找著這個mWindowManager是在哪裡執行個體化的,是不是上下來復原動著這個類都找不見?STOP!mWindowManager是在它爹那裡就執行個體化好的。下面代碼是在Window.java中的。

public void setWindowManager(WindowManager wm,
IBinder appToken,
String appName,
boolean hardwareAccelerated) {
...
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
//擷取了一個WindowManager
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
//通過這裡我們可以知道,上面擷取到的wm實際是WindowManagerImpl類型的。
}
通過上面的介紹,我們已經知道了Window中有負責承載布局的DecorView,有負責管理的WindowManager(事實上它只是個代理,後面會講它代理的是誰)。

DecorView
前面提到過,在Activity的onCreate()中通過setContentView()設定的布局實際是被放到DecorView中的。我們在圖中找到DecorView。

可以看到,DecorView繼承了FrameLayout,並且一般情況下,它會在先添加一個預設的布局。比如DecorCaptionView,它是從上到下放置自己的子布局的,相當於一個LinearLayout。通常它會有一個標題列,然後有一個容納內容的mContentRoot,這個布局的類型視情況而定。我們希望顯示的布局就是放到了mContentRoot中。

知識點:通過setContentView()設定的布局是被放到DecorView中,DecorView是視圖樹的最頂層。

WindowManager
前面已經提到過,WindowManager在Window中具有很重要的作用。我們先在圖中找到它。這裡需要先說明一點,在PhoneWindow中的mWindowManager實際是WindowManagerImpl類型的。WindowManagerImpl自然就是介面WindowManager的一個實作類別嘍。這一點是我沒有在圖中反映的。

WindowManager是在Activity執行attach()時被建立的,attach()方法是在onCreate()之前被調用的。關於Activity的建立可以看看我的這篇:【可能是史上最簡單的!一張圖3分鐘讓你明白Activity啟動流程,不看後悔!http://www.jianshu.com/p/9ecea420eb52】。
Activity.java

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){
...
mWindow = new PhoneWindow(this, window);
//建立Window
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
//注意!這裡就是在建立WindowManager。
//這個方法在前面已經說過了。
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
}
繼續看圖。WindowManagerImpl持有了PhoneWindow的引用,因此它可以對PhoneWindow進行管理。同時它還持有一個非常重要的引用mGlobal。這個mGlobal指向一個WindowManagerGlobal類型的單例對象,這個單例每個應用程式只有唯一的一個。在圖中,我說明了WindowManagerGlobal維護了本應用程式內所有Window的DecorView,以及與每一個DecorView對應關聯的ViewRootImpl。這也就是為什麼我前面提到過,WindowManager只是一個代理,實際的管理功能是通過WindowManagerGlobal實現的。我們來看個源碼的例子就比較清晰了。開始啦!

image
WimdowManagerImpl.java

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
...
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
//實際是通過WindowManagerGlobal實現的。
}
從上面的代碼可以看出,WindowManagerImpl確實只是WindowManagerGlobal的一個代理而已。同時,上面這個方法在整個Android的視圖架構流程中十分的重要。我們知道,在Activity執行onResume()後介面就要開始渲染了。原因是在onResume()時,會調用WindowManager的addView()方法(實際最後調用的是WindowManagerGlobal的addView()方法),把視圖添加到視窗上。結合我的這篇【可能是史上最簡單的!一張圖3分鐘讓你明白Activity啟動流程,不看後悔!http://www.jianshu.com/p/9ecea420eb52】看,可以協助你更好的理解Android的視圖架構。
ActivityThread.java

final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
...
ViewManager wm = a.getWindowManager();
//獲得WindowManager,實際是WindowManagerImpl
...
wm.addView(decor, l);
//添加視圖
...
wm.updateViewLayout(decor, l);
//需要重新整理的時候會走這裡
...
}
從上面可以看到,當Activity執行onResume()的時候就會添加視圖,或者重新整理視圖。需要解釋一點:WindowManager實現了ViewManager介面。

中所說,WindowManagerGlobal調用addView()的時候會把DecorView添加到它維護的數組中去,並且會建立另一個關鍵且極其重要的ViewRootImpl(這個必須要專門講一下)類型的對象,並且也會把它存到一個數組中維護。
WindowManagerGlobal.java

public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...
root = new ViewRootImpl(view.getContext(), display);
//重要角色登場
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
//儲存起來維護
mParams.add(wparams);
...
root.setView(view, wparams, panelParentView);
//設定必要屬性view是DecorView,panelParentView是PhoneWindow
...
}
可以看出ViewRootImpl是在Activity執行onResume()的時候才被建立的,並且此時才把DecorView傳進去讓它管理。

知識點:WindowManager是在onCreate()時被建立。它對視窗的管理能力實際是通過WindowManagerGlobal實現的。在onResume()是視圖才通過WindowManager被添加到視窗上。

ViewRootImpl
ViewRootImpl能夠和系統的WindowManagerService進行互動,並且管理著DecorView的繪製和視窗狀態。非常的重要。趕緊在圖中找到對應位置吧!

ViewRootImpl並不是一個View,而是負責管理檢視的。它配合系統來完成對一個Window內的視圖樹的管理。也可以看到,它持有了DecorView的引用,並且視圖樹它是視圖樹繪製的起點。因此,ViewRootImpl會稍微複雜一點,需要我們更深入的去瞭解,在圖中我標出了它比較重要的組成Surface和Choreographer等都會在後面提到。

到此,我們已經一起把第一張圖擼了一遍了,現在童鞋們因該對Android視圖架構有了大致的瞭解。下面將更進一步的去瞭解Android的繪製機制。

App總是卡頓到底是什麼原因?
下面將會詳細的講解為什麼我們設定的視圖能夠被繪製到螢幕上?這中間究竟隱藏著怎樣的離奇?看完之後,你自然就能夠從根源知道為什麼你的App會那麼卡,以及開始有思路著手解決這些卡頓。

image
同樣用一張圖來展示這個過程。由於Android繪製機制確實有點複雜,所以第一眼看到的時候你的內心中可能蹦騰了一萬隻草泥馬

用兩張圖告訴你,為什麼你的 App 會卡頓

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.