欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

android繪制,android繪制自定義地圖

Android - View 繪制流程

我們知道,在 Android 中,View 繪制主要包含 3 大流程:

公司主營(yíng)業(yè)務(wù):成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶(hù)真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶(hù)帶來(lái)驚喜。成都創(chuàng)新互聯(lián)公司推出碾子山免費(fèi)做網(wǎng)站回饋大家。

Android 中,主要有兩種視圖: View 和 ViewGroup ,其中:

雖然 ViewGroup 繼承于 View ,但是在 View 繪制三大流程中,某些流程需要區(qū)分 View 和 ViewGroup ,它們之間的操作并不完全相同,比如:

對(duì) View 進(jìn)行測(cè)量,主要包含兩個(gè)步驟:

對(duì)于第一個(gè)步驟,即求取 View 的 MeasureSpec ,首先我們來(lái)看下 MeasureSpec 的源碼定義:

MeasureSpec 是 View 的一個(gè)公有靜態(tài)內(nèi)部類(lèi),它是一個(gè) 32 位的 int 值,高 2 位表示 SpecMode(測(cè)量模式),低 30 位表示 SpecSize(測(cè)量尺寸/測(cè)量大小)。

MeasureSpec 將兩個(gè)數(shù)據(jù)打包到一個(gè) int 值上,可以減少對(duì)象內(nèi)存分配,并且其提供了相應(yīng)的工具方法可以很方便地讓我們從一個(gè) int 值中抽取出 View 的 SpecMode 和 SpecSize。

一個(gè) MeasureSpec 表達(dá)的是:該 View 在該種測(cè)量模式(SpecMode)下對(duì)應(yīng)的測(cè)量尺寸(SpecSize)。其中,SpecMode 有三種類(lèi)型:

對(duì) View 進(jìn)行測(cè)量,最關(guān)鍵的一步就是計(jì)算得到 View 的 MeasureSpec ,子View 在創(chuàng)建時(shí),可以指定不同的 LayoutParams (布局參數(shù)), LayoutParams 的源碼主要內(nèi)容如下所示:

其中:

LayoutParams 會(huì)受到父容器的 MeasureSpec 的影響,測(cè)量過(guò)程會(huì)依據(jù)兩者之間的相互約束最終生成子View 的 MeasureSpec ,完成 View 的測(cè)量規(guī)格。

簡(jiǎn)而言之,View 的 MeasureSpec 受自身的 LayoutParams 和父容器的 MeasureSpec 共同決定( DecorView 的 MeasureSpec 是由自身的 LayoutParams 和屏幕尺寸共同決定,參考后文)。也因此,如果要求取子View 的 MeasureSpec ,那么首先就需要知道父容器的 MeasureSpec ,層層逆推而上,即最終就是需要知道頂層View(即 DecorView )的 MeasureSpec ,這樣才能一層層傳遞下來(lái),這整個(gè)過(guò)程需要結(jié)合 Activity 的啟動(dòng)過(guò)程進(jìn)行分析。

我們知道,在 Android 中, Activity 是作為視圖組件存在,主要就是在手機(jī)上顯示視圖界面,可以供用戶(hù)操作, Activity 就是 Andorid 中與用戶(hù)直接交互最多的系統(tǒng)組件。

Activity 的基本視圖層次結(jié)構(gòu)如下所示:

Activity 中,實(shí)際承載視圖的組件是 Window (更具體來(lái)說(shuō)為 PhoneWindow ),頂層View 是 DecorView ,它是一個(gè) FrameLayout , DecorView 內(nèi)部是一個(gè) LinearLayout ,該 LinearLayout 由兩部分組成(不同 Android 版本或主題稍有差異): TitleView 和 ContentView ,其中, TitleView 就是標(biāo)題欄,也就是我們常說(shuō)的 TitleBar 或 ActionBar , ContentView 就是內(nèi)容欄,它也是一個(gè) FrameLayout ,主要用于承載我們的自定義根布局,即當(dāng)我們調(diào)用 setContentView(...) 時(shí),其實(shí)就是把我們自定義的布局設(shè)置到該 ContentView 中。

當(dāng) Activity 啟動(dòng)完成后,最終就會(huì)渲染出上述層次結(jié)構(gòu)的視圖。

因此,如果我們要求取得到子View 的 MeasureSpec ,那么第一步就是求取得到頂層View(即 DecorView )的 MeasureSpec 。大致過(guò)程如下所示:

經(jīng)過(guò)上述步驟求取得到 View 的 MeasureSpec 后,接下來(lái)就可以真正對(duì) View 進(jìn)行測(cè)量,求取 View 的最終測(cè)量寬/高:

Android 內(nèi)部對(duì)視圖進(jìn)行測(cè)量的過(guò)程是由 View#measure(int, int) 方法負(fù)責(zé)的,但是對(duì)于 View 和 ViewGroup ,其具體測(cè)量過(guò)程有所差異。

因此,對(duì)于測(cè)量過(guò)程,我們分別對(duì) View 和 ViewGroup 進(jìn)行分析:

綜上,無(wú)論是對(duì) View 的測(cè)量還是 ViewGroup 的測(cè)量,都是由 View#measure(int widthMeasureSpec, int heightMeasureSpec) 方法負(fù)責(zé),然后真正執(zhí)行 View 測(cè)量的是 View 的 onMeasure(int widthMeasureSpec, int heightMeasureSpec) 方法。

具體來(lái)說(shuō), View 直接在 onMeasure(...) 中測(cè)量并設(shè)置自己的最終測(cè)量寬/高。在默認(rèn)測(cè)量情況下, View 的測(cè)量寬/高由其父容器的 MeasureSpec 和自身的 LayoutParams 共同決定,當(dāng) View 自身的測(cè)量模式為 LayoutParams.UNSPECIFIED 時(shí),其測(cè)量寬/高為 android:minWidth / android:minHeight 和其背景寬/高之間的較大值,其余情況皆為自身 MeasureSpec 指定的測(cè)量尺寸。

而對(duì)于 ViewGroup 來(lái)說(shuō),由于布局特性的豐富性,只能自己手動(dòng)覆寫(xiě) onMeasure(...) 方法,實(shí)現(xiàn)自定義測(cè)量過(guò)程,但是總的思想都是先測(cè)量 子View 大小,最終才能確定自己的測(cè)量大小。

當(dāng)確定了 View 的測(cè)量大小后,接下來(lái)就可以來(lái)確定 View 的布局位置了,也即將 View 放置到屏幕具體哪個(gè)位置。

View 的布局過(guò)程由 View#layout(...) 負(fù)責(zé),其源碼如下:

View#layout(...) 主要就做了兩件事:

ViewGroup 的布局流程由 ViewGroup#layout(...) 負(fù)責(zé),其源碼如下:

可以看到, ViewGroup#layout(...) 最終也是通過(guò) View#layout(...) 完成自身的布局過(guò)程,一個(gè)注意的點(diǎn)是, ViewGroup#layout(...) 是一個(gè) final 方法,因此子類(lèi)無(wú)法覆寫(xiě)該方法,主要是 ViewGroup#layout(...) 方法內(nèi)部對(duì)子視圖動(dòng)畫(huà)效果進(jìn)行了相關(guān)設(shè)置。

由于 ViewGroup#layout(...) 內(nèi)部最終調(diào)用的還是 View#layout(...) ,因此, ViewGroup#onLayout(...) 就會(huì)得到回調(diào),用于處理 子View 的布局放置,其源碼如下:

由于不同的 ViewGroup ,其布局特性不同,因此 ViewGroup#onLayout(...) 是一個(gè)抽象方法,交由 ViewGroup 子類(lèi)依據(jù)自己的布局特性,擺放其 子View 的位置。

當(dāng) View 的測(cè)量大小,布局位置都確定后,就可以最終將該 View 繪制到屏幕上了。

View 的繪制過(guò)程由 View#draw(...) 方法負(fù)責(zé),其源碼如下:

其實(shí)注釋已經(jīng)寫(xiě)的很清楚了, View#draw(...) 主要做了以下 6 件事:

我們知道,在 Activity 啟動(dòng)過(guò)程中,會(huì)調(diào)用到 ActivityThread.handleResumeActivity(...) ,該方法就是 View 視圖繪制的起始之處:

可以看到, ActivityThread.handleResumeActivity(...) 主要就是獲取到當(dāng)前 Activity 綁定的 ViewManager ,最后調(diào)用 ViewManager.addView(...) 方法將 DecorView 設(shè)置到 PhoneWindow 上,也即設(shè)置到當(dāng)前 Activity 上。 ViewManager 是一個(gè)接口, WindowManager 繼承 ViewManager ,而 WindowManagerImpl 實(shí)現(xiàn)了接口 WindowManager ,此處的 ViewManager.addView(...) 實(shí)際上調(diào)用的是 WindowManagerImpl.addView(...) ,源碼如下所示:

WindowManagerImpl.addView(...) 內(nèi)部轉(zhuǎn)發(fā)到 WindowManagerGlobal.addView(...) :

在 WindowManagerGlobal.addView(...) 內(nèi)部,會(huì)創(chuàng)建一個(gè) ViewRootImpl 實(shí)例,然后調(diào)用 ViewRootImpl.setView(...) 將 ViewRootImpl 與 DecorView 關(guān)聯(lián)到一起:

ViewRootImpl.setView(...) 內(nèi)部首先關(guān)聯(lián)了傳遞過(guò)來(lái)的 DecorView (通過(guò)屬性 mView 指向 DecorView 即可建立關(guān)聯(lián)),然后最終調(diào)用 requestLayout() ,而 requestLayout() 內(nèi)部又會(huì)調(diào)用方法 scheduleTraversals() :

ViewRootImpl.scheduleTraversals() 內(nèi)部主要做了兩件事:

Choreographer.postCallback(...) 會(huì)申請(qǐng)一次 VSYNC 中斷信號(hào),當(dāng) VSYNC 信號(hào)到達(dá)時(shí),便會(huì)回調(diào) Choreographer.doFrame(...) 方法,內(nèi)部會(huì)觸發(fā)已經(jīng)添加的回調(diào)任務(wù), Choreographer 的回調(diào)任務(wù)有以下四種類(lèi)型:

因此, ViewRootImpl.scheduleTraversals(...) 內(nèi)部通過(guò) mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null) 發(fā)送的異步視圖渲染消息就會(huì)得到回調(diào),即回調(diào) mTra

Android繪制機(jī)制

Android視圖顯示流程是先繪制(CPU的工作)在渲染(GPU)的工作

CPU負(fù)責(zé)把UI組件計(jì)算成Polygons,Texture紋理,然后在交給GPU進(jìn)行柵格化渲染到屏幕上

繪制,畫(huà)畫(huà)這些都要先有畫(huà)布,Android上UI最終的畫(huà)布就是Surface

在B慢了之后,A在下下次脈沖加載之前,趁著這個(gè)空閑的時(shí)間,計(jì)算C,CPU就一直不會(huì)閑著了,這樣在脈沖到來(lái)時(shí),可能就已經(jīng)完成了B和C的計(jì)算,B,C都待投放到屏幕,多了個(gè)緩沖,解決了一幀慢,幀幀慢的問(wèn)題。

但需要重點(diǎn)說(shuō)明一下的是: 垂直同步機(jī)制是Android一直都有的,除了三緩沖,因?yàn)槿彌_會(huì)導(dǎo)致某一幀(比如C)在計(jì)算完很久之后才被選中投放到屏幕,即幀延后現(xiàn)象。而且選擇C去這個(gè)過(guò)程本身也是一系列計(jì)算,所以三緩沖是選擇性開(kāi)啟,當(dāng)雙緩沖造成的jank現(xiàn)象越來(lái)越嚴(yán)重,就開(kāi)啟去調(diào)節(jié)一下。

渲染的整體流程最好要限制在16ms內(nèi),如果大于16ms,會(huì)造成App的卡頓等性能問(wèn)題,渲染造成的問(wèn)題我們就要想辦法進(jìn)行優(yōu)化

五、Android繪制知識(shí)總結(jié)(Xfermode和硬件加速)

Xfermode表示圖層的混合模式,用于描述兩個(gè)圖層之間進(jìn)行融合時(shí),像素點(diǎn)進(jìn)行計(jì)算的規(guī)則。

在API16之前,Xfermode有3個(gè)子類(lèi):AvoidXfermode、PixelXorXfermode、PorterDuffXfermode。但在API16以后,前兩個(gè)已經(jīng)過(guò)時(shí),甚至從源碼里移除,所以我們只需學(xué)習(xí) PorterDuffXfermode 即可。

PorterDuffXfermode 最早是在1984年由Porter和Duff兩人發(fā)表的論文《Compositing Digital Images》中出現(xiàn),所以該混合模式也根據(jù)作者來(lái)命名。

PorterDuffXfermode 構(gòu)造函數(shù)需要指定一個(gè) PorterDuff.Mode ,而PorterDuff.Mode在以下地方都會(huì)涉及:

它提供18種模式可選項(xiàng):

各種模式下的效果如下圖所示:

這里可以發(fā)現(xiàn),兩種效果是不一樣的,谷歌官方給的是第一種,但是,通常情況應(yīng)該是第二種,具體原因可 參考該文章 。比如我們畫(huà)一個(gè)矩形,應(yīng)該按第二種效果來(lái)考慮,因?yàn)樵磮D和目標(biāo)圖大小不一致;如果畫(huà)相同大小的Bitmap,則按第一種做。

在實(shí)際應(yīng)用中,我們可以從以下三個(gè)方面來(lái)決定使用哪種模式:

1、沒(méi)有硬件加速:

invalidate the view hierarchy ------ draw the view hierarchy

2、有硬件加速:

invalidate the view hierarchy ------ record and update the display list ------ draw the display list

1、繪制不正確:可能使用了不支持硬件加速的操作, 需要關(guān)閉硬件加速或者繞過(guò)該操作

2、拋出異常:可能使用了不支持硬件加速的操作, 需要關(guān)閉硬件加速或者繞過(guò)該操作

在Android系統(tǒng)中,有4個(gè)不同級(jí)別的打開(kāi)或者關(guān)閉硬件加速操作:

1、Application級(jí)別:

application android:hardwareAccelerated="false"

默認(rèn)為true,用于控制這個(gè)app是否開(kāi)啟硬件加速。

2、Activity級(jí)別:

activity android:hardwareAccelerated="false"

3、Window級(jí)別:(只支持開(kāi)啟操作)

getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

4、View級(jí)別:(只支持關(guān)閉操作)

view.setLayerType(View.LAYER_TYPE_HARDWARE, null);

LAYER_TYPE_HARDWARE ,使用硬件加速(GPU)進(jìn)行繪制

LAYER_TYPE_SOFTWARE ,使用CPU進(jìn)行繪制

或者布局文件中,指定以下屬性:

android:layerType="software"

1、view.isHardwareAccelerated()

如果返回true,表示view掛在一個(gè)開(kāi)啟了硬件加速的Window之下,也就意味著,它在繪制時(shí),并不一定開(kāi)啟了硬件加速。

2、canvas.isHardwareAccelerated()

如果返回true,因?yàn)橹鴆anvas在繪制的時(shí)候啟用了硬件加速,盡量采用此方法來(lái)判斷是否開(kāi)啟了硬件加速。

網(wǎng)站標(biāo)題:android繪制,android繪制自定義地圖
文章位置:http://chinadenli.net/article34/dsgsppe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化電子商務(wù)移動(dòng)網(wǎng)站建設(shè)全網(wǎng)營(yíng)銷(xiāo)推廣云服務(wù)器響應(yīng)式網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

綿陽(yáng)服務(wù)器托管