国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

03.Android之View原理問題

FrozenMap / 3064人閱讀

摘要:這種自定義控件在原生控件提供的方法外,可以自己添加一些方法。從頂層父到子遞歸調(diào)用方法,方法又回調(diào)。

目錄介紹

3.0.0.1 View的繪制需要經(jīng)過哪些過程?有哪些常用回調(diào)方法?View的繪制流程的詳細(xì)流程是怎樣的?

3.0.0.2 View繪制流程,當(dāng)一個TextView的實例調(diào)用setText()方法后執(zhí)行了什么?請說一下原理……

3.0.0.3 requestLayout()、invalidate()與postInvalidate()有什么區(qū)別?

3.0.0.4 DecorView的作用是什么?DecorView中如何獲取ContentView以及Activity所設(shè)置的View?ViewRootIml如何和DecorView建立聯(lián)系?

3.0.0.5 getWidth()方法和getMeasureWidth()區(qū)別呢?為什么有時候用getWidth()或者getMeasureWidth()得到0?

3.0.0.6 平時寫的自定義控件有哪些?如何優(yōu)化自定義view?View的繪制流程說一下?自定義View的注意點?

3.0.0.7 View的wrap_content和match_parent效果一致的原因分析?getDefaultSize方法的處理邏輯?

3.0.0.8 ViewGroup(抽象類)的measure流程?getChildMeasureSpec獲取子元素MeasureSpec的要點?

3.0.0.9 View的layout過程?View的layout()源碼分析?LinearLayout的onLayout方法?View的測量寬高和最終寬高有什么區(qū)別?

3.0.1.0 draw的過程步驟是什么?View特殊方法setWillNotDraw是干什么用的?

3.0.1.1 View中x,y,translationX,translationY分別是什么?View平移時是否改變了left、top等原始參數(shù)?

3.0.1.2 MeasureSpec是什么?MeasureSpec的組成?測量模式SpecMode的類型和具體含義?MeasureSpec和LayoutParams的對應(yīng)關(guān)系?

3.0.1.3 如何獲取View的測量寬/高?如何在Activity啟動時獲得View的寬/高?Activity中獲得View寬高的4種辦法?

3.0.1.4 Activity啟動到最終加載ViewRoot(執(zhí)行三大流程)的流程是什么?

3.0.1.5 自定義View性能優(yōu)化有哪些?針對異常銷毀,自定義View如何優(yōu)化?如何避免創(chuàng)建大量對象?

好消息

博客筆記大匯總【15年10月到至今】,包括Java基礎(chǔ)及深入知識點,Android技術(shù)博客,Python學(xué)習(xí)筆記等等,還包括平時開發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題,長期更新維護(hù)并且修正,持續(xù)完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計500篇[近100萬字],將會陸續(xù)發(fā)表到網(wǎng)上,轉(zhuǎn)載請注明出處,謝謝!

鏈接地址:https://github.com/yangchong2...

如果覺得好,可以star一下,謝謝!當(dāng)然也歡迎提出建議,萬事起于忽微,量變引起質(zhì)變!所有的筆記將會更新到GitHub上,同時保持更新,歡迎同行提出或者push不同的看法或者筆記!

3.0.0.1 View的繪制需要經(jīng)過哪些過程?有哪些常用回調(diào)方法?View的繪制流程的詳細(xì)流程是怎樣的?

View的繪制需要經(jīng)過哪些過程?

measure:測量View的寬和高

View的measure方法是final類型方法——表明該方法無法被重載

View的measure方法會調(diào)用onMeasure方法,onMeasure會調(diào)用setMeasuredDimension方法設(shè)置View寬/高的測量值

layout:確定View在父控件中的放置位置

draw:負(fù)責(zé)將View繪制在屏幕上。技術(shù)博客大總結(jié)

有哪些常用回調(diào)方法?

構(gòu)造方法

onAttachToWindow:在包含View的Activity啟動時調(diào)用

onDetachFromWindow:在包含View的Activity退出或者View被remove時回調(diào)

onVisibilityChanged:當(dāng)View的可見狀態(tài)發(fā)生改變時調(diào)用

比較重要的概念

ViewRoot:連接WindowManager(外界訪問Window的入口)和DecorView(頂級View)的紐帶,View的三大流程均是通過ViewRoot來完成的。

DecorView:頂級View

DecorView是頂級View,本質(zhì)就是一個FrameLayout

包含了兩個部分,標(biāo)題欄和內(nèi)容欄

內(nèi)容欄id是content,也就是activity中setContentView所設(shè)置的部分,最終將布局添加到id為content的FrameLayout中

View的繪制流程的詳細(xì)流程是怎樣的?技術(shù)博客大總結(jié)

View的繪制流程是從ViewRoot的PerformTraversals方法開始的。大概的流程如下所示

performTraversals會依次調(diào)用performMeasure, performLayout, performDraw三個方法,這三個方法分別完成頂層View的measure,layout,draw方法,onMeasure又會調(diào)用所有子元素的measure過程,直到完成整個View樹的遍歷。同理,performLayout, performDraw的傳遞流程與performMeasure相似。唯一不同在于,performDraw的傳遞過程在draw方法中通過dispatchDraw實現(xiàn),但沒有本質(zhì)區(qū)別。

Measure過程后可以調(diào)用getMeasureWidth和getMeasureHeight方法獲取View測量后的寬高,與getWidth和getHeight的區(qū)別是:getMeasuredHeight()返回的是原始測量高度,與屏幕無關(guān),getHeight()返回的是在屏幕上顯示的高度。實際上在當(dāng)屏幕可以包裹內(nèi)容的時候,他們的值是相等的,只有當(dāng)view超出屏幕后,才能看出他們的區(qū)別。當(dāng)超出屏幕后,getMeasuredHeight()等于getHeight()加上屏幕之外沒有顯示的高度。

Layout過程確定View四個頂點的位置和實際的寬高。

Draw過程確定View的顯示,只有draw方法完成后View的內(nèi)容才會出現(xiàn)在屏幕上。

3.0.0.2 View繪制流程,當(dāng)一個TextView的實例調(diào)用setText()方法后執(zhí)行了什么?請說一下原理……

View的繪制流程主要分為三步:

onMeasure:測量視圖的大小,從頂層父View到子View遞歸調(diào)用measure()方法,measure()調(diào)用onMeasure()方法,onMeasure()方法完成繪制工作。

onLayout:確定視圖的位置,從頂層父View到子View遞歸調(diào)用layout()方法,父View將上一步measure()方法得到的子View的布局大小和布局參數(shù),將子View放在合適的位置上。

onDraw:繪制最終的視圖,首先ViewRoot創(chuàng)建一個Canvas對象,然后調(diào)用onDraw()方法進(jìn)行繪制。onDraw()方法的繪制流程為

① 繪制視圖背景。

② 繪制畫布的圖層。 技術(shù)博客大總結(jié)

③ 繪制View內(nèi)容。

④ 繪制子視圖,如果有的話。

⑤ 還原圖層。

⑥ 繪制滾動條。

3.0.0.3 requestLayout()、invalidate()與postInvalidate()有什么區(qū)別?requestLayout()何時不會觸發(fā)onDraw()?

invalidate() postInvalidate()

invalidate()該方法遞歸調(diào)用父View的invalidateChildInParent()方法,直到調(diào)用ViewRootImpl的invalidateChildInParent()方法,最終觸發(fā)ViewRootImpl的performTraversals()方法,此時mLayoutRequestede為false,不會觸發(fā)onMesaure()與onLayout()方法,有可能會觸發(fā)onDraw()方法。

共同點:都是調(diào)用onDraw()方法,然后去達(dá)到重繪view的目的

區(qū)別:invalidate()用于主線程,postInvalidate()用于子線程

requestLayout()

該方法會遞歸調(diào)用父窗口的requestLayout()方法,直到觸發(fā)ViewRootImpl的performTraversals()方法,此時mLayoutRequestede為true,會觸發(fā)onMesaure()與onLayout()方法,不一定會觸發(fā)onDraw()方法。

當(dāng)view確定自身已經(jīng)不再適合現(xiàn)有的區(qū)域時,該view本身調(diào)用這個方法要求parent view(父類的視圖)重新調(diào)用他的onMeasure、onLayout來重新設(shè)置自己位置。特別是當(dāng)view的layoutparameter發(fā)生改變,并且它的值還沒能應(yīng)用到view上時,這時候適合調(diào)用這個方法requestLayout()。requestLayout調(diào)用onMeasure和onLayout,不一定調(diào)用onDraw技術(shù)博客大總結(jié)

如何選擇

一般說來需要重新布局就調(diào)用requestLayout()方法,需要重新繪制就調(diào)用invalidate()方法。

requestLayout()何時不會觸發(fā)onDraw()?

如果沒有改變控件的leftrighttopbottom就不會觸發(fā)onDraw()

invalidate()在什么情況下不會觸發(fā)onDraw?

在ViewGroup中,invalidate默認(rèn)不重新繪制子view。

如何讓ViewGroup在invalidate時會觸發(fā)onDraw?技術(shù)博客大總結(jié)

本質(zhì)需要將ViewGroup的dirtyOpaque設(shè)置為false

1.在構(gòu)造函數(shù)中調(diào)用setWillNotDraw(false);

2.給ViewGroup設(shè)置背景。調(diào)用setBackground。

3.0.0.4 DecorView的作用是什么?DecorView中如何獲取ContentView以及Activity所設(shè)置的View?ViewRootIml如何和DecorView建立聯(lián)系?

DecorView的作用是什么?

DecorView是頂級View,本質(zhì)就是一個FrameLayout

包含了兩個部分,標(biāo)題欄和內(nèi)容欄,內(nèi)容欄id是content,也就是activity中setContentView所設(shè)置的部分,最終將布局添加到id為content的FrameLayout中技術(shù)博客大總結(jié)

DecorView中如何獲取ContentView以及Activity所設(shè)置的View?

獲取content:ViewGroup content = findViewById(R.android.id.content)

獲取設(shè)置的View:content.getChidlAt(0)

ViewRootIml如何和DecorView建立聯(lián)系?技術(shù)博客大總結(jié)

Activity對象在ActivityThread中創(chuàng)建完畢后,會將DecorView添加到Window中

同時會創(chuàng)建ViewRootImpl,調(diào)用ViewRoot的setView方法將ViewRootImpl和DevorView建立關(guān)聯(lián)

root = new ViewRootImpl(view.getContext(), display);
root.setView(view, wparams, panelParentView);

ViewRoot為什么要和DecorView建立關(guān)聯(lián)

DecorView等View的三大流程需要通過ViewRoot完成

3.0.0.5 getWidth()方法和getMeasureWidth()區(qū)別呢?為什么有時候用getWidth()或者getMeasureWidth()得到0?

getWidth()方法和getMeasureWidth()區(qū)別呢

getMeasureWidth()

getMeasureWidth()方法在measure()過程結(jié)束后就可以獲取到了,另外,getMeasureWidth()方法中的值是通過setMeasuredDimension()方法來進(jìn)行設(shè)置的

這里mMeasuredWidth & MEASURED_SIZE_MASK表示的是測量階段結(jié)束之后,view真實的值。

public final int getMeasuredWidth() {
    return mMeasuredWidth & MEASURED_SIZE_MASK;
}

getWidth()

getWidth()方法要在layout()過程結(jié)束后才能獲取到,getWidth()方法中的值則是通過視圖右邊的坐標(biāo)減去左邊的坐標(biāo)計算出來的。

mRight和mLeft是什么值,是在什么時候被設(shè)置的。具體看layout()過程中源碼

@ViewDebug.ExportedProperty(category = "layout")
public final int getWidth() {
    return mRight - mLeft;
}

為什么有時候用getWidth()或者getMeasureWidth()得到0

問題描述:使用getMeasuredWidth()和getMeasuredHeight()方法,無論是在onCreate()、onStart()、onResume()中調(diào)用,都無法得到控件的長度、和寬度。如下圖,測量的結(jié)果為0。

解釋:技術(shù)博客大總結(jié)

因為View的Measure過程和Activity的生命周期方法不是同步執(zhí)行的,所以無法保證Activity執(zhí)行了onCreate()、onStart()、onResume()時某個View已經(jīng)測量完畢了,如果View還沒有測量完畢,那么獲得寬/高就是0。

后來覺得這種解釋有點牽強(qiáng),比如

解決控件測量寬高問題

如下所示

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    test();
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    getWidth(4);
}

private void test(){
    getWidth(1);
    
    marqueeView.measure(0, 0);
    getWidth(2);
    
    marqueeView.post(new Runnable() {
        @Override
        public void run() {
            getWidth(3);
        }
    });
}

private void getWidth(int a){
    int width2 = marqueeView.getWidth();
    int measuredWidth2 = marqueeView.getMeasuredWidth();
    Log.e(a+"MainActivity-----",width2+"-----"+measuredWidth2);
}

//11-28 17:03:17.559 15990-15990/com.yc.cn.ycbanner E/1MainActivity-----: 0-----0
//11-28 17:03:17.567 15990-15990/com.yc.cn.ycbanner E/2MainActivity-----: 0-----760
//11-28 17:03:17.684 15990-15990/com.yc.cn.ycbanner E/3MainActivity-----: 960-----960
//11-28 17:03:17.685 15990-15990/com.yc.cn.ycbanner E/4MainActivity-----: 960-----960

什么時候測量寬高不等于實際寬高?

MeasuredWidth/height!=getWidth/Height()的場景:更改View的布局參數(shù)并進(jìn)行重新布局后,就會導(dǎo)致測量寬高!=實際寬高

3.0.0.6 平時寫的自定義控件有哪些?如何優(yōu)化自定義view?View的繪制流程說一下?自定義View的注意點?

平時寫的自定義控件有哪些?

1組合控件。這種自定義控件不需要我們自己繪制,而是使用原生控件組合成的新控件。如標(biāo)題欄,recyclerView封裝控件。

2繼承原有的控件。這種自定義控件在原生控件提供的方法外,可以自己添加一些方法。比如圖片縮放控件,進(jìn)度條控件。

3完全自定義控件:這個View上所展現(xiàn)的內(nèi)容全部都是我們自己繪制出來的。比如百分比進(jìn)度條控件

如何優(yōu)化自定義 view

為了加速你的view,對于頻繁調(diào)用的方法,需要盡量減少不必要的代碼。先從onDraw開始,需要特別注意不應(yīng)該在這里做內(nèi)存分配的事情,因為它會導(dǎo)致GC,從而導(dǎo)致卡頓。在初始化或者動畫間隙期間做分配內(nèi)存的動作。不要在動畫正在執(zhí)行的時候做內(nèi)存分配的事情。

你還需要盡可能的減少onDraw被調(diào)用的次數(shù),大多數(shù)時候?qū)е耾nDraw都是因為調(diào)用了invalidate().因此請盡量減少調(diào)用invaildate()的次數(shù)。如果可能的話,盡量調(diào)用含有4個參數(shù)的invalidate()方法而不是沒有參數(shù)的invalidate()。沒有參數(shù)的invalidate會強(qiáng)制重繪整個view。技術(shù)博客大總結(jié)

另外一個非常耗時的操作是請求layout。任何時候執(zhí)行requestLayout(),會使得Android UI系統(tǒng)去遍歷整個View的層級來計算出每一個view的大小。如果找到有沖突的值,它會需要重新計算好幾次。另外需要盡量保持View的層級是扁平化的,這樣對提高效率很有幫助。

如果你有一個復(fù)雜的UI,你應(yīng)該考慮寫一個自定義的ViewGroup來執(zhí)行他的layout操作。與內(nèi)置的view不同,自定義的view可以使得程序僅僅測量這一部分,這避免了遍歷整個view的層級結(jié)構(gòu)來計算大小。這個PieChart 例子展示了如何繼承ViewGroup作為自定義view的一部分。PieChart 有子views,但是它從來不測量它們。而是根據(jù)他自身的layout法則,直接設(shè)置它們的大小。

View的繪制流程說一下?

View的繪制流程:OnMeasure()——>OnLayout()——>OnDraw()

第一步:OnMeasure():測量視圖大小。從頂層父View到子View遞歸調(diào)用measure方法,measure方法又回調(diào)OnMeasure。

第二步:OnLayout():確定View位置,進(jìn)行頁面布局。從頂層父View向子View的遞歸調(diào)用view.layout方法的過程,即父View根據(jù)上一步measure子View所得到的布局大小和布局參數(shù),將子View放在合適的位置上。

第三步:OnDraw():繪制視圖。ViewRoot創(chuàng)建一個Canvas對象,然后調(diào)用OnDraw()。六個步驟:①、繪制視圖的背景;②、保存畫布的圖層(Layer);③、繪制View的內(nèi)容;④、繪制View子視圖,如果沒有就不用;⑤、還原圖層(Layer);⑥、繪制滾動條。技術(shù)博客大總結(jié)

自定義View的注意點?

View需要支持wrap_content、padding

ViewGroup需要支持子View的margin和自身的padding

盡量不要在View中使用Handler,View已經(jīng)有post系列方法

View如果有線程或者動畫,需要及時停止(onDetachedFromWindow會在View被remove時調(diào)用)——避免內(nèi)存泄露

View如果有滑動嵌套情形,需要處理好滑動沖突

3.0.0.7 View的wrap_content和match_parent效果一致的原因分析?getDefaultSize方法的處理邏輯?

View的wrap_content和match_parent效果一致的原因分析?

根據(jù)View的onMeasure方法中的getDefaultSize方法,我們可以發(fā)現(xiàn)在兩種模式下,View的測量值等于該View的測量規(guī)格MeasureSpec中的尺寸。

View的MeasureSpec本質(zhì)是由自身的LayoutParams和父容器的MeasureSpec決定的。

當(dāng)View為wrap_content時,該View的模式為AT_MOST,且尺寸specSize為父容器的剩余空間大小。

當(dāng)View為match_parent時,該View的模式跟隨父容器的模式(AT_MOST/EXACTLY), 且尺寸specSize為父容器的剩余空間大小。

因此getDefaultSize中無論View是哪種模式,最終測量寬/高均等于尺寸specSize,因此兩種屬性效果是完全一樣的(View的大小充滿了父容器的剩余空間)技術(shù)博客大總結(jié)

除非給定View固定的寬/高,View的specSize才會等于該固定值。

getDefaultSize方法的處理邏輯?

getDefaultSize: 根據(jù)建議獲取的最小寬高和測量規(guī)格,決定實際的測量寬高

UNSPECIFIED模式:測量寬高 = 建議的最小寬高

EXACTLY / AT_MOST模式:測量寬高 = specSize技術(shù)博客大總結(jié)

View的getDefaultSize源碼要點(決定了View寬高的測量值)

UNSPECIFIED模式時,寬/高為第一個參數(shù)也就是getSuggestedMinimumWidth()獲取的建議最小值

AT_MOST(wrap_content)和EXACTLY(match_parent/具體值dp等)這兩個模式下,View寬高的測量值為當(dāng)前View的MeasureSpec(測量規(guī)格)中指定的尺寸specsize

3.0.0.8 ViewGroup(抽象類)的measure流程?getChildMeasureSpec獲取子元素MeasureSpec的要點?

ViewGroup(抽象類)的measure流程?

ViewGroup沒有onMeasure方法,只定義了measureChildren方法(onMeasure根據(jù)不同布局難以統(tǒng)一)

measureChildren中遍歷所有子元素并調(diào)用measureChild方法

measureChild方法中會獲取子View的MeasureSpec(getChildMeasureSpec),然后調(diào)用子元素View的measure方法進(jìn)行測量

getChildMeasureSpec獲取子元素MeasureSpec的要點?

子View的MeasureSpec是根據(jù)自身的LayoutParams和父容器SpecMode生成

當(dāng)子View的布局參數(shù)為wrap_content,且父容器模式為AT_MOST時,效果與子元素布局為match_parent是一樣的。因此當(dāng)子View的布局參數(shù)為wrap_content時,需要給指定默認(rèn)的寬/高

LinearLayout的onMeasure()分析

ViewGroup因為布局的不同,無法統(tǒng)一onMeasure方法,具體內(nèi)容根據(jù)布局的不同而不同,這里直接以LinearLayout進(jìn)行分析

onMeasure會根據(jù)orientation選擇measureVertical或者measureHorizontal進(jìn)行測量

measureVertical本質(zhì)是遍歷子元素,并執(zhí)行子元素的measure方法,并獲得子元素的總高度以及子元素在豎直方向上的margin等。技術(shù)博客大總結(jié)

最終LinearLayout會測量自己的大小,在orientation的方向上,如果布局是match_parent或者具體數(shù)值,測量過程與View一致(高度為specSize);如果布局是wrap_content,高度是所有子元素高度總和,且不會超過父容器的剩余空間,最終高度需要考慮在豎直方向上的padding

3.0.0.9 View的layout過程?View的layout()源碼分析?LinearLayout的onLayout方法?View的測量寬高和最終寬高有什么區(qū)別?

View的layout過程?

使用layout方法確定View本身的位置

layout中調(diào)用onLayout方法確定所有子View的位置

View的layout()源碼分析?

調(diào)用setFrame()設(shè)置View四個定點位置(即初始化mLeft,mRight,mTop,mBottom的值)

之后調(diào)用onLayout確定子View位置,該方法類似于onMeasure,View和ViewGroup中均沒有實現(xiàn),具體實現(xiàn)與具體布局有關(guān)。

LinearLayout的onLayout方法?

根據(jù)orientation選擇調(diào)用layoutVertical或者layoutHorizontal

layoutVertical中會遍歷所有子元素并調(diào)用setChildFrame(里面直接調(diào)用子元素的layout方法)

層層傳遞下去完成了整個View樹的layout過程

setChildFrame中的寬/高實際就是子元素的測量寬/高(getMeasure…后直接傳入)

View的測量寬高和最終寬高有什么區(qū)別?技術(shù)博客大總結(jié)

等價于getMeasuredWidth和getWidth有什么區(qū)別

getWidth = mRight - mLeft,結(jié)合源碼測量值和最終值是完全相等的。

區(qū)別在于:測量寬高形成于measure過程,最終寬高形成于layout過程(賦值時機(jī)不同)

也有可能導(dǎo)致兩者不一致:強(qiáng)行重寫View的layout方法,在傳參方面改變最終寬/高(雖然這樣毫無實際意義)

某些情況下,View需要多次measure才能確定自己的測量寬高,在前幾次測量中等到的值可能有最終寬高不一致。但是最終結(jié)果上,測量寬高=最終寬高

3.0.1.0 draw的過程步驟是什么?View特殊方法setWillNotDraw是干什么用的?

draw的過程步驟是什么?

繪制背景(drawBackground(canvas))

繪制自己(onDraw)

繪制children(dispatchDraw)-遍歷調(diào)用所有子View的draw方法

繪制裝飾(如onDrawScollBars)

View特殊方法setWillNotDraw是干什么用的?

若一個View不繪制任何內(nèi)容,需要將該標(biāo)志置為true,系統(tǒng)會進(jìn)行相應(yīng)優(yōu)化

默認(rèn)View不開啟該標(biāo)志位技術(shù)博客大總結(jié)

默認(rèn)ViewGroup開啟該標(biāo)志位

如果我們自定義控件繼承自ViewGroup并且本身不進(jìn)行繪制時,就可以開啟該標(biāo)志位

當(dāng)該ViewGroup明確通過onDraw繪制內(nèi)容時,就需要顯式關(guān)閉WILL_NOT_DRAW標(biāo)志位。

3.0.1.1 View中x,y,translationX,translationY分別是什么?View平移時是否改變了left、top等原始參數(shù)?

View中x,y,translationX,translationY分別是什么?

x,y是View當(dāng)前左上角的坐標(biāo)

translationX,translationY是在滑動/動畫后,View當(dāng)前位置和View最原始位置的距離。

因此得出等式:x(View左上角當(dāng)前位置) = left(View左上角初始位置) + translationX(View左上角偏移的距離)

View平移時是否改變了left、top等原始參數(shù)?技術(shù)博客大總結(jié)

View平移時top、left等參數(shù)不變,改變的是x,y,tranlsationX和tranlsationY

3.0.1.2 MeasureSpec是什么?MeasureSpec的組成?測量模式SpecMode的類型和具體含義?MeasureSpec和LayoutParams的對應(yīng)關(guān)系?

MeasureSpec是什么?

MeasureSpec是一種“測量規(guī)則”或者“測量說明書”,決定了View的測量過程

View的MeasureSpec會根據(jù)自身的LayoutParamse和父容器的MeasureSpec生成。

最終根據(jù)View的MeasureSpec測量出View的寬/高(測量時數(shù)據(jù)并非最終寬高)

MeasureSpec的組成?

MeasureSpec代表一個32位int值,高2位是SpecMode,低30位是SpecSize

SpecMode是指測量模式

SpecSize是指在某種測量模式下的大小

類MesaureSpec提供了用于SpecMode和SpecSize打包和解包的方法

測量模式SpecMode的類型和具體含義?技術(shù)博客大總結(jié)

UNSPECIFIED:父容器不對View有任何限制,一般用于系統(tǒng)內(nèi)部

EXACTLY:精準(zhǔn)模式,View的最終大小就是SpecSize指定的值(對應(yīng)于LayoutParams的match_parent和具體的數(shù)值)

AT_MOST:最大值模式,大小不能大于父容器指定的值SpecSize(對應(yīng)于wrap_content)

MeasureSpec和LayoutParams的對應(yīng)關(guān)系?

View的MeasureSpec是需要通過自身的LayoutParams和父容器的MeasureSpec一起才能決定

DecorView(頂級View)是例外,其本身MeasureSpec由窗口尺寸和自身LayoutParams共同決定

MeasureSpec一旦確定,onMeasure中就可以確定View的測量寬/高

3.0.1.3 如何獲取View的測量寬/高?如何在Activity啟動時獲得View的寬/高?Activity中獲得View寬高的4種辦法?

如何獲取View的測量寬/高?

在measure完成后,可以通過getMeasuredWidth/Height()方法,就能獲得View的測量寬高

在一定極端情況下,系統(tǒng)需要多次measure,因此得到的值可能不準(zhǔn)確,最好的辦法是在onLayout方法中獲得測量寬/高或者最終寬/高

如何在Activity啟動時獲得View的寬/高?

Activity的生命周期與View的measure不是同步運(yùn)行,因此在onCreate/onStart/onResume均無法正確得到

若在View沒有測量好時,去獲得寬高,會導(dǎo)致最終結(jié)果為0

有四種辦法去正確獲得寬高

Activity中獲得View寬高的4種辦法?技術(shù)博客大總結(jié)

onWindowFocusChanged

View已經(jīng)初始化完畢,可以獲得寬高;Activity得到焦點和失去焦點均會調(diào)用一次(頻繁onResume和onPause會導(dǎo)致頻繁調(diào)用)

view.post(runnable)

通過post將一個runnable投遞到消息隊列尾部;等到Looper調(diào)用次runnable時,View已經(jīng)完成初始化

ViewTreeObserver

使用ViewTreeObserver的接口,可以在View樹狀態(tài)改變或者View樹內(nèi)部View的可見性改變時,onGlobalLayout會被回調(diào);能正確獲取View寬/高

view.measure

3.0.1.4 Activity啟動到最終加載ViewRoot(執(zhí)行三大流程)的流程是什么?

Activity啟動到最終加載ViewRoot(執(zhí)行三大流程)的流程是什么?

Activity調(diào)用startActivity方法,最終會調(diào)用ActivityThread的handleLaunchActivity方法

handleLaunchActivity會調(diào)用performLauchActivity方法(會調(diào)用Activity的onCreate,并完成DecorView的創(chuàng)建)和handleResumeActivity方法

handleResumeActivity方法會做四件事:performResumeActivity(調(diào)用activity的onResume方法)、getDecorView(獲取DecorView)、getWindowManager(獲取WindowManager)、WindowManager.addView(decor, 1)

WindowManager.addView(decor, 1)本質(zhì)是調(diào)用WindowManagerGlobal的addView方法。其中主要做兩件事:1、創(chuàng)建ViewRootImpl實例 2、root.setView(decor, ….)將DecorView作為參數(shù)添加到ViewRoot中,這樣就將DecorView加載到了Window中

ViewRootImpl還有一個方法performTraveals方法,用于讓ViewTree開始View的工作流程:其中會調(diào)用performMeasure/Layout/Draw()三個方法,分別對應(yīng)于View的三大流程。

3.0.1.5 自定義View性能優(yōu)化有哪些?針對異常銷毀,自定義View如何優(yōu)化?如何避免創(chuàng)建大量對象?

自定義View性能優(yōu)化有哪些?

避免過度繪制

盡量減少或簡化計算

避免創(chuàng)建大量對象造成頻繁GC

禁止或避免I/O操作

onDraw中避免冗余代碼、避免創(chuàng)建對象

復(fù)合View,要減少布局層級。

狀態(tài)和恢復(fù)和保存

開啟硬件加速

合理使用invalidate的參數(shù)版本。

減少冗余代碼:不要使用Handler,因為已經(jīng)有post系列方法.

使用的線程和動畫,要在onDetachedFromWindow中進(jìn)行清理工作。

要妥善處理滑動沖突。

避免過度繪制

像素點能畫一次就不要多次繪制,以及繪制看不到的背景

開發(fā)者選項里內(nèi)的工具,只對xml布局有效果,看不到自定義View的過度繪制,仍然需要注意。

盡量減少或簡化計算

不要做無用計算。盡可能的復(fù)用計算結(jié)果。技術(shù)博客大總結(jié)

沒有數(shù)據(jù),或者數(shù)據(jù)較少的時候應(yīng)如何處理,沒有事件需要響應(yīng)的時候如何處理。

應(yīng)該避免在for或while循環(huán)中做計算。比如:去計算屏幕寬度等信息。

避免創(chuàng)建大量對象造成頻繁GC

應(yīng)該避免在for或while循環(huán)中new對象。這是減少內(nèi)存占用量的有效方法。

禁止或避免I/O操作

I/O操作對性能損耗極大,不要在自定義View中做IO操作。

onDraw中避免冗余代碼、避免創(chuàng)建對象

onDraw中禁止new對象.如:不應(yīng)該在ondraw中創(chuàng)建Paint對象。Paint類提供了reset方法。可以在初始化View時創(chuàng)建對象。

要避免冗余代碼,提高效率。

復(fù)合View,要減少布局層級。

復(fù)合控件:繼承自現(xiàn)有的LinearLayout等ViewGroup,然后組合多個控件來實現(xiàn)效果。這種實現(xiàn)方法要注意減少布局層級,層級越高性能越差。

狀態(tài)和恢復(fù)和保存

Activity還會因為內(nèi)存不足或者旋轉(zhuǎn)屏幕而導(dǎo)致重建Activity,自定義View也要去進(jìn)行自我狀態(tài)的保存和讀取。

在onSaveInstanceState()保存狀態(tài);在onRestoreInstanceState()恢復(fù)狀態(tài)

開啟硬件加速

合理使用invalidate的參數(shù)版本。技術(shù)博客大總結(jié)

避免任何請款下之際調(diào)用默認(rèn)參數(shù)的invalidate

調(diào)用有參數(shù)的invalidate進(jìn)行局部和子View刷新,能夠提高性能。

減少冗余代碼:不要使用Handler,因為已經(jīng)有post系列方法

View已經(jīng)有post系列方法,沒有必要重復(fù)去寫。

可以直接使用,最終會投遞到主線程的Handler中

使用的線程和動畫,要在onDetachedFromWindow中進(jìn)行清理工作。

View如果有線程或者動畫,需要及時停止.

View的onDetachedFromWindow會在View被remove時調(diào)用,在該方法內(nèi)進(jìn)行終止

這樣能避免內(nèi)存泄露

要妥善處理滑動沖突。

View如果有滑動嵌套情形,需要處理好滑動沖突

關(guān)于其他內(nèi)容介紹 01.關(guān)于博客匯總鏈接

1.技術(shù)博客匯總

2.開源項目匯總

3.生活博客匯總

4.喜馬拉雅音頻匯總

5.其他匯總

02.關(guān)于我的博客

我的個人站點:www.yczbj.org, www.ycbjie.cn

github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/...

簡書:http://www.jianshu.com/u/b7b2...

csdn:http://my.csdn.net/m0_37700275

喜馬拉雅聽書:http://www.ximalaya.com/zhubo...

開源中國:https://my.oschina.net/zbj161...

泡在網(wǎng)上的日子:http://www.jcodecraeer.com/me...

郵箱:yangchong211@163.com

阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV

segmentfault頭條:https://segmentfault.com/u/xi...

掘金:https://juejin.im/user/593943...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72864.html

相關(guān)文章

  • 08.AndroidView事件問題

    摘要:內(nèi)部是調(diào)用效果是移動的內(nèi)容,因此需要在的父控件中調(diào)用。和的情況相似,手機(jī)屏幕向下移動,為正值手機(jī)屏幕向上移動,為負(fù)值。 目錄介紹 8.0.0.1 簡述Android的事件分發(fā)機(jī)制?dispatchTouchEvent方法的作用是什么?說下View和ViewGroup分發(fā)事件? 8.0.0.2 onInterceptTouchEvent方法作用是什么?onTouchEvent的方法的作...

    lavnFan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<