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

flutterndk的簡單介紹

Android圖形渲染原理上

對于Android開發(fā)者來說,我們或多或少有了解過Android圖像顯示的知識點,剛剛學(xué)習(xí)Android開發(fā)的人會知道,在Actvity的onCreate方法中設(shè)置我們的View后,再經(jīng)過onMeasure,onLayout,onDraw的流程,界面就顯示出來了;對Android比較熟悉的開發(fā)者會知道,onDraw流程分為軟件繪制和硬件繪制兩種模式,軟繪是通過調(diào)用Skia來操作,硬繪是通過調(diào)用Opengl ES來操作;對Android非常熟悉的開發(fā)者會知道繪制出來的圖形數(shù)據(jù)最終都通過GraphiBuffer內(nèi)共享內(nèi)存?zhèn)鬟f給SurfaceFlinger去做圖層混合,圖層混合完成后將圖形數(shù)據(jù)送到幀緩沖區(qū),于是,圖形就在我們的屏幕顯示出來了。

十余年的阿合奇網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。成都全網(wǎng)營銷的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整阿合奇建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)從事“阿合奇網(wǎng)站設(shè)計”,“阿合奇網(wǎng)站推廣”以來,每個客戶項目都認(rèn)真落實執(zhí)行。

但我們所知道的Activity或者是應(yīng)用App界面的顯示,只屬于Android圖形顯示的一部分。同樣可以在Android系統(tǒng)上展示圖像的WebView,F(xiàn)lutter,或者是通過Unity開發(fā)的3D游戲,他們的界面又是如何被繪制和顯現(xiàn)出來的呢?他們和我們所熟悉的Acitvity的界面顯示又有什么異同點呢?我們可以不借助Activity的setView或者InflateView機制來實現(xiàn)在屏幕上顯示出我們想要的界面嗎?Android系統(tǒng)顯示界面的方式又和IOS,或者Windows等系統(tǒng)有什么區(qū)別呢?……

去探究這些問題,比僅僅知道Acitvity的界面是如何顯示出來更加的有價值,因為想要回答這些問題,就需要我們真正的掌握Android圖像顯示的底層原理,當(dāng)我們掌握了底層的顯示原理后,我們會發(fā)現(xiàn)WebView,F(xiàn)lutter或者未來會出現(xiàn)的各種新的圖形顯示技術(shù),原來都是大同小異。

我會花三篇文章的篇幅,去深入的講解Android圖形顯示的原理,OpenGL ES和Skia的繪制圖像的方式,他們?nèi)绾问褂茫约八麄冊贏ndroid中的使用場景,如開機動畫,Activity界面的軟件繪制和硬件繪制,以及Flutter的界面繪制。那么,我們開始對Android圖像顯示原理的探索吧。

在講解Android圖像的顯示之前,我會先講一下屏幕圖像的顯示原理,畢竟我們圖像,最終都是在手機屏幕上顯示出來的,了解這一塊的知識會讓我們更容易的理解Android在圖像顯示上的機制。

圖像顯示的完整過程,分為下面幾個階段:

圖像數(shù)據(jù)→CPU→顯卡驅(qū)動→顯卡(GPU)→顯存(幀緩沖)→顯示器

我詳細(xì)介紹一下這幾個階段:

實際上顯卡驅(qū)動,顯卡和顯存,包括數(shù)模轉(zhuǎn)換模塊都是屬于顯卡的模塊。但為了能能詳細(xì)的講解經(jīng)歷的步驟,這里做了拆分。

當(dāng)顯存中有數(shù)據(jù)后,顯示器又是怎么根據(jù)顯存里面的數(shù)據(jù)來進行界面的顯示的呢?這里以LCD液晶屏為例,顯卡會將顯存里的數(shù)據(jù),按照從左至右,從上到下的順序同步到屏幕上的每一個像素晶體管,一個像素晶體管就代表了一個像素。

如果我們的屏幕分辨率是1080x1920像素,就表示有1080x1920個像素像素晶體管,每個橡素點的顏色越豐富,描述這個像素的數(shù)據(jù)就越大,比如單色,每個像素只需要1bit,16色時,只需要4bit,256色時,就需要一個字節(jié)。那么1080x1920的分辨率的屏幕下,如果要以256色顯示,顯卡至少需要1080x1920個字節(jié),也就是2M的大小。

剛剛說了,屏幕上的像素數(shù)據(jù)是從左到右,從上到下進行同步的,當(dāng)這個過程完成了,就表示一幀繪制完成了,于是會開始下一幀的繪制,大部分的顯示屏都是以60HZ的頻率在屏幕上繪制完一幀,也就是16ms,并且每次繪制新的一幀時,都會發(fā)出一個垂直同步信號(VSync)。我們已經(jīng)知道,圖像數(shù)據(jù)都是放在幀緩沖中的,如果幀緩沖的緩沖區(qū)只有一個,那么屏幕在繪制這一幀的時候,圖像數(shù)據(jù)便沒法放入幀緩沖中了,只能等待這一幀繪制完成,在這種情況下,會有很大了效率問題。所以為了解決這一問題,幀緩沖引入兩個緩沖區(qū),即 雙緩沖機制 。雙緩沖雖然能解決效率問題,但會引入一個新的問題。當(dāng)屏幕這一幀還沒繪制完成時,即屏幕內(nèi)容剛顯示一半時,GPU 將新的一幀內(nèi)容提交到幀緩沖區(qū)并把兩個緩沖區(qū)進行交換后,顯卡的像素同步模塊就會把新的一幀數(shù)據(jù)的下半段顯示到屏幕上,造成畫面撕裂現(xiàn)象。

為了解決撕裂問題,就需要在收到垂直同步的時候才將幀緩沖中的兩個緩沖區(qū)進行交換。Android4.1黃油計劃中有一個優(yōu)化點,就是CPU和GPU都只有收到垂直同步的信號時,才會開始進行圖像的繪制操作,以及緩沖區(qū)的交換工作。

我們已經(jīng)了解了屏幕圖像顯示的原理了,那么接著開始對Android圖像顯示的學(xué)習(xí)。

從上一章已經(jīng)知道,計算機渲染界面必須要有GPU和幀緩沖。對于Linux系統(tǒng)來說,用戶進程是沒法直接操作幀緩沖的,但我們想要顯示圖像就必須要操作幀緩沖,所以Linux系統(tǒng)設(shè)計了一個虛擬設(shè)備文件,來作為對幀緩沖的映射,通過對該文件的I/O讀寫,我們就可以實現(xiàn)讀寫屏操作。幀緩沖對應(yīng)的設(shè)備文件于/dev/fb* ,*表示對多個顯示設(shè)備的支持, 設(shè)備號從0到31,如/dev/fb0就表示第一塊顯示屏,/dev/fb1就表示第二塊顯示屏。對于Android系統(tǒng)來說,默認(rèn)使用/dev/fb0這一個設(shè)幀緩沖作為主屏幕,也就是我們的手機屏幕。我們Android手機屏幕上顯示的圖像數(shù)據(jù),都是存儲在/dev/fb0里,早期AndroidStuio中的DDMS工具實現(xiàn)截屏的原理就是直接讀取/dev/fb0設(shè)備文件。

我們知道了手機屏幕上的圖形數(shù)據(jù)都存儲在幀緩沖中,所以Android手機圖像界面的原理就是將我們的圖像數(shù)據(jù)寫入到幀緩沖內(nèi)。那么,寫入到幀緩沖的圖像數(shù)據(jù)是怎么生成的,又是怎樣加工的呢?圖形數(shù)據(jù)是怎樣送到幀緩沖去的,中間經(jīng)歷了哪些步驟和過程呢?了解了這幾個問題,我們就了解了Android圖形渲染的原理,那么帶著這幾個疑問,接著往下看。

想要知道圖像數(shù)據(jù)是怎么產(chǎn)生的,我們需要知道 圖像生產(chǎn)者 有哪些,他們分別是如何生成圖像的,想要知道圖像數(shù)據(jù)是怎么被消費的,我們需要知道 圖像消費者 有哪些,他們又分別是如何消費圖像的,想要知道中間經(jīng)歷的步驟和過程,我們需要知道 圖像緩沖區(qū) 有哪些,他們是如何被創(chuàng)建,如何分配存儲空間,又是如何將數(shù)據(jù)從生產(chǎn)者傳遞到消費者的,圖像顯示是一個很經(jīng)典的消費者生產(chǎn)者的模型,只有對這個模型各個模塊的擊破,了解他們之間的流動關(guān)系,我們才能找到一條更容易的路徑去掌握Android圖形顯示原理。我們看看谷歌提供的官方的架構(gòu)圖是怎樣描述這一模型的模塊及關(guān)系的。

如圖, 圖像的生產(chǎn)者 主要有MediaPlayer,CameraPrevier,NDK,OpenGl ES。MediaPlayer和Camera Previer是通過直接讀取圖像源來生成圖像數(shù)據(jù),NDK(Skia),OpenGL ES是通過自身的繪制能力生產(chǎn)的圖像數(shù)據(jù); 圖像的消費者 有SurfaceFlinger,OpenGL ES Apps,以及HAL中的Hardware Composer。OpenGl ES既可以是圖像的生產(chǎn)者,也可以是圖像的消費者,所以它也放在了圖像消費模塊中; 圖像緩沖區(qū) 主要有Surface以及前面提到幀緩沖。

Android圖像顯示的原理,會僅僅圍繞 圖像的生產(chǎn)者 , 圖像的消費者 , 圖像緩沖區(qū) 來展開,在這一篇文章中,我們先看看Android系統(tǒng)中的圖像消費者。

SurfaceFlinger是Android系統(tǒng)中最重要的一個圖像消費者,Activity繪制的界面圖像,都會傳遞到SurfaceFlinger來,SurfaceFlinger的作用主要是接收圖像緩沖區(qū)數(shù)據(jù),然后交給HWComposer或者OpenGL做合成,合成完成后,SurfaceFlinger會把最終的數(shù)據(jù)提交給幀緩沖。

那么SurfaceFlinger是如何接收圖像緩沖區(qū)的數(shù)據(jù)的呢?我們需要先了解一下Layer(層)的概念,一個Layer包含了一個Surface,一個Surface對應(yīng)了一塊圖形緩沖區(qū),而一個界面是由多個Surface組成的,所以他們會一一對應(yīng)到SurfaceFlinger的Layer中。SurfaceFlinger通過讀取Layer中的緩沖數(shù)據(jù),就相當(dāng)于讀取界面上Surface的圖像數(shù)據(jù)。Layer本質(zhì)上是 Surface和SurfaceControl的組合 ,Surface是圖形生產(chǎn)者和圖像消費之間傳遞數(shù)據(jù)的緩沖區(qū),SurfaceControl是Surface的控制類。

前面在屏幕圖像顯示原理中講到,為了防止圖像的撕裂,Android系統(tǒng)會在收到VSync垂直同步時才會開始處理圖像的繪制和合成工作,而Surfaceflinger作為一個圖像的消費者,同樣也是遵守這一規(guī)則,所以我們通過源碼來看看SurfaceFlinger是如何在這一規(guī)則下,消費圖像數(shù)據(jù)的。

SurfaceFlinger專門創(chuàng)建了一個EventThread線程用來接收VSync。EventThread通過Socket將VSync信號同步到EventQueue中,而EventQueue又通過回調(diào)的方式,將VSync信號同步到SurfaceFlinger內(nèi)。我們看一下源碼實現(xiàn)。

上面主要是SurfaceFlinger初始化接收VSYNC垂直同步信號的操作,主要有這幾個過程:

經(jīng)過上面幾個步驟,我們接收VSync的初始化工作都準(zhǔn)備好了,EventThread也開始運轉(zhuǎn)了,接著看一下EventThread的運轉(zhuǎn)函數(shù)threadLoop做的事情。

threadLoop主要是兩件事情

mConditon又是怎么接收VSync的呢?我們來看一下

可以看到,mCondition的VSync信號實際是DispSyncSource通過onVSyncEvent回調(diào)傳入的,但是DispSyncSource的VSync又是怎么接收的呢?在上面講到的SurfaceFlinger的init函數(shù),在創(chuàng)建EventThread的實現(xiàn)中,我們可以發(fā)現(xiàn)答案—— mPrimaryDispSync 。

DispSyncSource的構(gòu)造方法傳入了mPrimaryDispSync,mPrimaryDispSync實際是一個DispSyncThread線程,我們看看這個線程的threadLoop方法

DispSyncThread的threadLoop會通過mPeriod來判斷是否進行阻塞或者進行VSync回調(diào),那么mPeriod又是哪兒被設(shè)置的呢?這里又回到SurfaceFlinger了,我們可以發(fā)現(xiàn)在SurfaceFlinger的 resyncToHardwareVsync 函數(shù)中有對mPeriod的賦值。

可以看到,這里最終通過HWComposer,也就是硬件層拿到了period。終于追蹤到了VSync的最終來源了, 它從HWCompser產(chǎn)生,回調(diào)至DispSync線程,然后DispSync線程回調(diào)到DispSyncSource,DispSyncSource又回調(diào)到EventThread,EventThread再通過Socket分發(fā)到MessageQueue中 。

我們已經(jīng)知道了VSync信號來自于HWCompser,但SurfaceFlinger并不會一直監(jiān)聽VSync信號,監(jiān)聽VSync的線程大部分時間都是休眠狀態(tài),只有需要做合成工作時,才會監(jiān)聽VSync,這樣即保證圖像合成的操作能和VSync保持一致,也節(jié)省了性能。SurfaceFlinger提供了一些主動注冊監(jiān)聽VSync的操作函數(shù)。

可以看到,只有當(dāng)SurfaceFlinger調(diào)用 signalTransaction 或者 signalLayerUpdate 函數(shù)時,才會注冊監(jiān)聽VSync信號。那么signalTransaction或者signalLayerUpdate什么時候被調(diào)用呢?它可以由圖像的生產(chǎn)者通知調(diào)用,也可以由SurfaceFlinger根據(jù)自己的邏輯來判斷是否調(diào)用。

現(xiàn)在假設(shè)App層已經(jīng)生成了我們界面的圖像數(shù)據(jù),并調(diào)用了 signalTransaction 通知SurfaceFlinger注冊監(jiān)聽VSync,于是VSync信號便會傳遞到了MessageQueue中了,我們接著看看MessageQueue又是怎么處理VSync的吧。

MessageQueue收到VSync信號后,最終回調(diào)到了SurfaceFlinger的 onMessageReceived 中,當(dāng)SurfaceFlinger接收到VSync后,便開始以一個圖像消費者的角色來處理圖像數(shù)據(jù)了。我們接著看SurfaceFlinger是以什么樣的方式消費圖像數(shù)據(jù)的。

VSync信號最終被SurfaceFlinger的onMessageReceived函數(shù)中的INVALIDATE模塊處理。

INVALIDATE的流程如下:

handleMessageTransaction的處理比較長,處理的事情也比較多,它主要做的事情有這些

handleMessageRefresh函數(shù),便是SurfaceFlinger真正處理圖層合成的地方,它主要下面五個步驟。

我會詳細(xì)介紹每一個步驟的具體操作

合成前預(yù)處理會判斷Layer是否發(fā)生變化,當(dāng)Layer中有新的待處理的Buffer幀(mQueuedFrames0),或者mSidebandStreamChanged發(fā)生了變化, 都表示Layer發(fā)生了變化,如果變化了,就調(diào)用signalLayerUpdate,注冊下一次的VSync信號。如果Layer沒有發(fā)生變化,便只會做這一次的合成工作,不會注冊下一次VSync了。

重建Layer棧會遍歷Layer,計算和存儲每個Layer的臟區(qū), 然后和當(dāng)前的顯示設(shè)備進行比較,看Layer的臟區(qū)域是否在顯示設(shè)備的顯示區(qū)域內(nèi),如果在顯示區(qū)域內(nèi)的話說明該layer是需要繪制的,則更新到顯示設(shè)備的VisibleLayersSortedByZ列表中,等待被合成

rebuildLayerStacks中最重要的一步是 computeVisibleRegions ,也就是對Layer的變化區(qū)域和非透明區(qū)域的計算,為什么要對變化區(qū)域做計算呢?我們先看看SurfaceFlinger對界面顯示區(qū)域的分類:

還是以這張圖做例子,可以看到我們的狀態(tài)欄是半透明的,所以它是一個opaqueRegion區(qū)域,微信界面和虛擬按鍵是完全不透明的,他是一個visibleRegion,除了這三個Layer外,還有一個我們看不到的Layer——壁紙,它被上方visibleRegion遮擋了,所以是coveredRegion

對這幾個區(qū)域的概念清楚了,我們就可以去了解computeVisibleRegions中做的事情了,它主要是這幾步操作:

Android自定義View之區(qū)塊選擇器

先來看下效果吧:

我們來分析這個view需要實現(xiàn)哪些效果。

別害怕有這么多的功能,我們一個一個來實現(xiàn)。首先是刻度尺,這個簡單。由于完整的刻度尺是比屏幕寬度大的,因此我們先來了解幾個概念:

這里手機屏幕的寬度是width,刻度尺的寬度的時maxWidth,我們其實只需要繪制手機屏幕可見的部分就可以了,這里的offset表示手機屏幕的左邊與刻度尺左邊的偏移量。

了解了這個概念,我們就來開始寫吧,定義一個View,處理下構(gòu)造都指向3個參數(shù)的那個,然后統(tǒng)一做初始化:

我們在onMeasure中處理了wrap_content的高度。然后在onSizeChanged中獲取尺寸參數(shù):

接著就開始繪制吧:

這里的titles代表了刻度的標(biāo)識,每一個元素代表一個刻度(這里我字節(jié)寫死了,實際上可以通過方法set,也不一定是時間,能代表刻度的都可以)。通過rate設(shè)置長短刻度的比例,這里我設(shè)置了1:1。運行一下看看,目前僅僅能看到從0開始,看不到完整的刻度尺,我們需要實現(xiàn)touch事件產(chǎn)生移動才有效果。

我們重寫onTouchEvent來實現(xiàn)滑動效果:

我們計算出每次move事件的X方向的變化量dx,然后通過這個dx改變offset,并且處理一下邊界的情況。然后調(diào)用postInvalidate刷新界面。

運行一下看看!現(xiàn)在我們可以滑動刻度尺了。但是好像還有點問題,平時我們使用ScrollView的時候用力劃一下,可以看到手指離開了屏幕,但是內(nèi)容還可以繼續(xù)滾動。而目前我們自定義的這個view只能通過手指滑動,如果手指離開屏幕就不能滑動了。這樣的體驗顯然不夠好,我們來實現(xiàn)這個慣性滑動的效果吧!

要實現(xiàn)慣性滑動,我們需要用到兩個類:VelocityTracker,OverScroller。

VelocityTracker簡介

view滑動助手類OverScroller

velocityTracker.computeCurrentVelocity方法的第二個參數(shù)表示最大慣性速度,這里我設(shè)置8000,避免刻度尺過快的滑動。通過調(diào)用scroller.fling方法將計算出的速度交給scroller,然后在computeScroll方法中獲取當(dāng)前值,并與上一次的值做差算出變化量dx,同樣用這個dx變化offset刷新界面實現(xiàn)滑動效果。

刻度尺完成了,接下來是不可選的灰色區(qū)域。我采用兩個int值表示在刻度尺的區(qū)域,刻度尺的每個刻度表示一個最小單位,前一個int表示在刻度尺的起始位置,后一個int表示占據(jù)的刻度數(shù)量。

我用一個list存放設(shè)置的不可選區(qū)域,然后在另一個list中存放轉(zhuǎn)換成RectF的位置信息。這里的RectF是在相對于整體刻度尺而言的,因此繪制到屏幕的時候需要減去offset,并且需要考慮只有部分在屏幕可見的情況。避免在onDraw方法中創(chuàng)建過多臨時變量,我聲明一個成員變量tempRect,用來保存繪制時的臨時參數(shù)。

完成了不可選區(qū)域,可選區(qū)域也是同樣的。由于只能有一個可選區(qū)域,我們只需要定義一個RectF。額外需要考慮與不可選區(qū)域相交時會變色,我定了一個overlapping表示是否相交,通過RectF的intersects方法判斷。

通過前面的分析,我們知道這個view中的事件有很多種:點擊,移動刻度尺,移動選中區(qū)域,擴展選中區(qū)域。我們定義這四種類型便于后續(xù)的事件處理:

然后改造一下onTouchEvent:

performClick會在你重寫onTouchEvent時as提示你需要重寫的方法,因為你可能沒有考慮到如果給這個view設(shè)置OnClickListener的情況。如果你沒有在onTouchEvent中調(diào)用performClick,那么setOnClickListener方法就失效了。

你可能注意到這一次比較復(fù)雜,并且還有一個linking字段,表示是否正在聯(lián)動,我解釋一下這個聯(lián)動的概念:通過gif其實你可能注意到,當(dāng)我移動或者擴展選中區(qū)域的時候,如果移動到了屏幕的邊界,后面的刻度尺就會跟著移動,實際上這個時候選中區(qū)域在屏幕中的位置沒有改變,只是刻度尺移動了。一開始我也是通過dx來改變offset,但是存在一個問題,移動到屏幕邊緣之后,手指可以移動的區(qū)域已經(jīng)很小了,不會產(chǎn)生足夠的dx(手指不移動的話,不會有新的touch事件產(chǎn)生)。最好的體驗是我把手機移動到屏幕邊緣,刻度尺就會自己按照一定的速率移動直到最大offset或者最小offset。于是我使用了Handler,當(dāng)滿足條件后發(fā)送消息,表示開始進行聯(lián)動,會按照固定速度產(chǎn)生一個dx改變offset。當(dāng)然,在離開屏幕邊緣的時候還需要及時取消handler的任務(wù)。

至此,功能基本已經(jīng)實現(xiàn)了,運行一下看看效果吧~

后面需要做什么那?現(xiàn)在這個view只能自己玩,我需要它與其他view有交互,比如選中什么區(qū)域,狀態(tài)的改變生么的。

聲明兩個接口,并在適當(dāng)時候回調(diào)它們的方法,這樣外部就能感知view的狀態(tài)變化。

后面的話就是根據(jù)業(yè)務(wù)添加一些api了,例如添加不可選區(qū)域,改變刻度范圍什么,一切都看需求了。

想學(xué)習(xí)更多Android知識,或者獲取相關(guān)資料請加入Android開發(fā)交流群:1018342383。 有面試資源系統(tǒng)整理分享,Java語言進階和Kotlin語言與Android相關(guān)技術(shù)內(nèi)核,APP開發(fā)框架知識, 360°Android App全方位性能優(yōu)化。Android前沿技術(shù),高級UI、Gradle、RxJava、小程序、Hybrid、 移動架構(gòu)師專題項目實戰(zhàn)環(huán)節(jié)、React Native、等技術(shù)教程!架構(gòu)師課程、NDK模塊開發(fā)、 Flutter等全方面的 Android高級實踐技術(shù)講解。還有在線答疑

Android網(wǎng)絡(luò)核心

Http?報文格式:狀態(tài)行、請求頭(響應(yīng)頭)、請求正文(響應(yīng)正文)

狀態(tài)行:http版本,地址、請求方式,空格劃分

請求頭(響應(yīng)頭):數(shù)據(jù)編碼格式信息,cookie信息

空白行

請求正文:如果是get方法則沒有,post則有

Http?是基于tcp的應(yīng)用層協(xié)議,只是一份協(xié)議,其實還是靠tcp傳輸,1.0版本無法復(fù)用,1.1版本修復(fù)了這個問題,keep-alive發(fā)送請求后保存一段時間,這樣可以復(fù)用

缺點:1.每次都需要重新建立連接

2.所有傳輸?shù)脙?nèi)容都是明文,無法驗證對方得身份,保證數(shù)據(jù)安全性

3.header里攜帶得內(nèi)容過大,在一定程度上增加了傳輸?shù)贸杀?/p>

Https:?Http+SSL+TCP(應(yīng)用層、安全層、傳輸層)

Https請求流程:

第一步:客戶端和服務(wù)端確認(rèn)加密算法和協(xié)議。其實挺復(fù)雜的,會分為以下2部分

1.客戶端會將自身支持的秘鑰算法套件(Cipher?Suite)發(fā)送給服務(wù)器

2.服務(wù)器根據(jù)自身支持的秘鑰算法套件,選擇雙發(fā)都支持的加密算法套件,并告知客戶端。

Cipher?Suite的名字里包含了四部分信息:

a.密鑰交換算法:用于決定客戶端與服務(wù)器之間在握手的過程中如何認(rèn)證,用到的算法包括RSA,ECDH,PSK等

b.加密算法:用于加密消息流,該名稱后通常會帶有兩個數(shù)字,分別表示密鑰的長度和初始向量的長度,比如DES?56/56,?RC2?56/128,?RC4???????????????128/128,?AES?128/128,?AES?256/256

c.報文認(rèn)證信息碼(MAC)算法:用于創(chuàng)建報文摘要,確保消息的完整性(沒有被篡改),算法包括MD5,SHA等。

d.PRF(偽隨機數(shù)函數(shù)):用于生成“master?secret”。

例如:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA

免費的數(shù)字證書簽發(fā)機構(gòu):Let's?Encrypt

SPDY:(HTTP、SPDY、SSL、TCP)

1.多路復(fù)用TCP通道,降低HTTP的高延時

2.允許請求設(shè)置優(yōu)先級

3.header數(shù)據(jù)壓縮

4.基于SSL的安全傳輸

Http2.0:

Http3.0:采用了UDP傳輸

Android歷屆大廠面試真題及答案

Android從零開始到精通

Android架構(gòu)師成長視頻

某機構(gòu)全套最新視頻

Tcp?ip協(xié)議全套書籍

NDK開發(fā)書本

Android10大開源框架刨析視頻

阿里Android面試題集及答案

Flutter快速入門

Java?最新Springboot2.0與spring?boot1.5學(xué)習(xí)視頻

還要需要iOS、或者是Java其他視頻的可以私聊我

鏈接:

提取碼:brx9

復(fù)制這段內(nèi)容后打開百度網(wǎng)盤手機App,操作更方便哦

Android端開發(fā)的工作是否真的難找?

與一個在行業(yè)里干了六七年的Android前輩聊了聊,得出以下結(jié)論以供參考。

首先Android開發(fā)的工作在一線城市并難找,但很多都是去填坑的,招過去就把人往死里用,而且這些項目所使用的技術(shù)也比較老舊,這也意味著開發(fā)效率高不到哪去,純粹的人肉BUG修復(fù)機。最主要的是工資也比后端低20%-30%。

而且一線城市的大公司或大國企不太愿意養(yǎng)移動端開發(fā)或者說是整個開發(fā)團隊,有需求人家就直接找外包;小公司也是迫于項目的需求才去招移動端開發(fā),但項目結(jié)束后要么叫你走人,要么叫你轉(zhuǎn)vue / react 開發(fā)。近年來招Flutter開發(fā)的也比較多。

除了移動互聯(lián)網(wǎng)應(yīng)用的Android 開發(fā),其他方向的開發(fā)更加小眾,更底層,需要懂NDK/C++,用的技術(shù)也更冷門,出了問題都找不到解決辦法,自然用人需求也更少。

希望新人入行慎重考慮。

Android 圖形系統(tǒng)(Graphics)

本文將從三個方面介紹Android 圖形系統(tǒng)。

圖形系統(tǒng)提供繪圖和圖形處理支持。

Android 框架提供了各種用于 2D 和 3D 圖形渲染的 API、圖片解碼庫,以及各種Driver支持。

? 繪圖API:2D引擎 Skia,3D引擎 OpenGL ES,RenderScript,OpenCV和Vulkan。

? 圖片解碼庫:jpg,png,gif等。

應(yīng)用開發(fā)者可通過三種方式將圖像繪制到屏幕:

? Canvas : 2D圖形API,Android View樹實際的繪制者。

? OpenGL ES : 嵌入式設(shè)備的OpenGL 三維圖形API子集。

? Vulkan :跨平臺的2D和3D繪圖引擎,Android 7.0后支持,NDK。

整個圖形系統(tǒng)架構(gòu)是一個生產(chǎn)者和消費者模式,五層依次介紹:

2D繪制:Canvas api / view 的子類 (button ,list)/自定義view

3D繪制:應(yīng)用直接使用OpenGL 接口繪制圖形(PixelFlinger對應(yīng)的是openGl 1.0 ,GUP driver 對應(yīng)的是2.0和3.0)

所有情況下的繪圖都渲染到一個包含 GraphicBuffer的Surface上,當(dāng)一塊 Surface 顯示在屏幕上時,就是用戶所看到的窗口。

? Canvas:畫布,2D圖形API,Android View樹實際的渲染者。

? Skia繪制:Android4.0之前默認(rèn)使用,主線程通過CPU完成繪圖指令操作,在復(fù)雜場景下單幀容易超過16ms導(dǎo)致卡頓。

WindowManagerService(WMS)窗口管理服務(wù),管理系統(tǒng)中所有的窗口。

? 管理window (view的容器)

? Window與surface對應(yīng),一塊顯示區(qū)域。添加一個window,就是 WMS 為其分配一塊 Surface 的過程。

Google 在Android source官網(wǎng)提示:

這里就對這些控件進行簡單介紹:

Surface : Handle onto a raw buffer that is being managed by the screen compositor.

Surface 對應(yīng)一塊屏幕緩沖區(qū)。生產(chǎn)者是: SurfaceTexture、MediaRecorder 等,消費者是: OpenGL、MediaPlayer 或 CameraDevice等。每個window對應(yīng)一個Surface。Canvas或OpenGL ES等最終都渲染到Surface上。

? Flutter在Android平臺上也是直接渲染到Surface。例如:一個Activity/Dialog都是一個Surface,它承載了上層的圖形數(shù)據(jù),與SurfaceFlinger側(cè)的Layer相對應(yīng)。

Canvas(畫布)實現(xiàn)由 Skia 圖形庫提供。為了確保兩個客戶端不會同時更新某個緩沖區(qū),使用以下命令處理畫布鎖:

使用雙緩沖機制,有自己的 surface,View只是一個透明的占位符,Surface可以在后臺線程中繪制。雙緩沖機制提高渲染效率,獨立線程

繪制,提升流暢性。適合一些場景:需要界面迅速更新、UI繪制時間長、對幀率要求較高的情況。

提供訪問和控制Surface 相關(guān)的方法 。通過SurfaceView的getHolder()函數(shù)可以獲取SurfaceHolder對象,Surface 就在SurfaceHolder對象內(nèi)。

addCallback(SurfaceHolder.Callbackcallback) /Canvas lockCanvas() /unlockCanvasAndPost(Canvascanvas)

SurfaceTexture: Surface 和 OpenGL ES (GLES) 紋理(Texture)的組合。將圖像流轉(zhuǎn)為 OpenGL 外部紋理。

TextureView:持有 SurfaceTexture,將圖像處理為 OpenGL 紋理更新到 HardwareLayer。

GLSurfaceView:加入 EGL 管理,自帶 GL 上下文和 GL 渲染線程

這些View通常涉及到Android音視頻相關(guān),需要高效的渲染能力。如下面的SurfaceTexture在camera中的應(yīng)用。

簡稱Buffer, 一個Buffer包含一幀圖像,Buffer由gralloc分配和回收。Buffer 屬性包含:width, height, format, usage等

BufferQueue 的引入是為了解決顯示和性能問題。

? Surface屬于APP進程,Layer屬于系統(tǒng)進程,如果它們之間只用一個Buffer,會存在顯示和性能問題。

? 一些Buffer用于繪制,一些Buffer用于顯示,雙方處理完之后,交換一下Buffer,提高效率。

? BufferQueue中包含多個Buffer對象。

Android圖形系統(tǒng)包含了兩對生產(chǎn)者和消費者模型,它們都通過BufferQueue進行連接:

1.Canvas和OpenGL ES生產(chǎn)圖形數(shù)據(jù),SurfaceFlinger消費圖形數(shù)據(jù)。

2.SurfaceFlinger合成所有圖層的圖形數(shù)據(jù),Display顯示合成結(jié)果。

code:frameworks/native/services/surfaceflinger

? Surface表示APP進程的一個窗口,承載了窗口的圖形數(shù)據(jù)。

? SurfaceFlinger是系統(tǒng)進程合成所有窗口的系統(tǒng)服務(wù),負(fù)責(zé)合成所有Surface提供的圖形數(shù)據(jù),然后送顯到屏幕。

? SurfaceFlinger既是上層應(yīng)用的消費者,又是Display的生產(chǎn)者,起到了承上啟下的作用。

數(shù)據(jù)流:

合成示意圖:

在介紹Vsync機制之前先介紹兩個重要概念:

屏幕刷新率:屏幕每秒鐘可以刷新多少次。60HZ刷新率,16.7ms刷新一次。(120HZ/8.3ms),硬件指標(biāo)。

GPU 繪制幀率:GPU 每秒能夠合成繪制多少幀。

軟件層觸發(fā) View 繪制的時機是隨機的,當(dāng)下一次屏幕刷新時,屏幕從 Frame Buffer 中拿到的數(shù)據(jù)還是“幀1”的數(shù)據(jù),導(dǎo)致“丟幀”。

每隔 16ms 硬件層發(fā)出 vsync 信號,應(yīng)用層接收到此信號后會觸發(fā)UI 的渲染流程,同時 vsync 信號也會觸發(fā) SurfaceFlinger 讀取Buffer 中的數(shù)據(jù),進行合成顯示到屏幕上。

總結(jié):Vsync機制將 CPU 和 GPU 的開始時間與屏幕刷新強行拖拽到同一起跑線

Android提供的Graphics流程相對比較復(fù)雜對其進行具象后的流程如下兩張圖所示:

Activity的啟動流程這一篇夠了

來了小伙子,先自我介紹一下吧

什么?你精通Android系統(tǒng)?來,你給我說下Activity的啟動流程。

Activity的啟動過程是系統(tǒng)中比較有代表意義的過程,涉及到了各個進程之間的相互交互,以及生命周期的回調(diào)控制,這也是為什么在面試過程出現(xiàn)頻率這么高的原因之一。

Activity的啟動流程在API28以后變成了事務(wù)啟動的方式,相比之前版本的邏輯有了一些變化,但是萬變不離其宗,大致流程還是類似的,只是增加了一些類,用來更好的劃分職責(zé),更優(yōu)的處理邏輯。

在開始之前,我們先簡單普及下基礎(chǔ)知識。

我們都知道進程與進程之間是數(shù)據(jù)隔離的,無法相互訪問數(shù)據(jù),所以進程之間通信是靠Binder來完成的。

面試官可能會問你 為什么會用Binder通信,Binder相比Socket有什么優(yōu)勢呢?

然而果然被追問了 為啥Binder能做到1次拷貝,而其他的技術(shù)是2次拷貝

好,可以描述下具體的映射怎么做的么?....

我們以 點擊Launcher的一個icon 為開始,整體扯一下Activity的啟動過程,桌面其實就是LauncherApp的一個Activity

最終調(diào)用performLaunchActivity方法創(chuàng)建activity和context并將其做關(guān)聯(lián),然后通過mInstrumentation.callActivityOnCreate()-Activity.performCreate()-Activity.onCreate()回調(diào)到了Activity的生命周期。

啟動一個Activity一般通過startActivity()

關(guān)于Android進階、架構(gòu)設(shè)計、NDK、跨平臺、底層源碼,KT,F(xiàn)lutter,以及面試的資料在我的Github上面可自行查看

項目地址:

我們先看下正常啟動Activity的方式,一般我們都會通過以下的方式啟動一個新的Activity。

其實這是在Activity中的調(diào)用方式,調(diào)用的即是父類Activity的startActivity()方法,因參數(shù)不同分為兩個方法,具體如下

最終調(diào)用的是startActivityForResult()

核心邏輯是調(diào)用了Instrumentation.execStartActivity()

ActivityManager.getService()這個獲取的是誰? 邏輯是從IActivityManagerSingleton.get()獲取,那IActivityManagerSingleton又是誰? IActivityManagerSingleton是這么定義的Singleton IActivityManagerSingleton get取出來的是IActivityManager,看這個大寫I開頭就知道是一個接口,實際調(diào)用過的是它的實現(xiàn)ActivityManagerService。 ActivityManagerService. startActivity()

mActivityStartController.obtainStarter實際調(diào)用的是ActivityStarter.execute(),連帶調(diào)用到ActivityStarter.startActivity()

ActivityStarter.startActivityUnchecked()連帶調(diào)用ActivityStackSupervisor.resumeFocusedStackTopActivityLocked();

targetStack為ActivityStack對象,ActivityStack.resumeTopActivityUncheckedLocked()

ActivityStack.resumeTopActivityInnerLocked()調(diào)用了mStackSupervisor.startSpecificActivityLocked(next, true, true);其中mStackSupervisor為ActivityStackSupervisor。 ActivityStackSupervisor.startSpecificActivityLocked()中調(diào)用 ActivityStackSupervisor.realStartActivityLocked()

注意這個clientTransaction對象,通過這種方式初始化

ClientLifecycleManager.scheduleTransaction(clientTransaction);

transaction.schedule();就要找到

mClient即是以上描述的ApplicationThread,因此我們跟進ApplicationThread.scheduleTransaction()

我靠,調(diào)用了ActivityThread.scheduleTransaction(transaction),但是ActivityThread并沒有scheduleTransaction(),所以我們找他繼承的類ClientTransactionHandler,發(fā)現(xiàn)ClientTransactionHandler果然有scheduleTransaction()

以上消息通過ActivityThread H對象進行發(fā)送具體解析也在ActivityThread中

我們可以看下TransactionExecutor.execute(transaction);

這里我們主要看下executeCallbacks()方法

transaction.getCallbacks()就是上述過程中ClientTransaction創(chuàng)建過程賦值的LaunchActivityItem對象,因此主要看下LaunchActivityItem.execute()

此時的client為ActivityThread,因此調(diào)用ActivityThread.handleLaunchActivity()

主要跟進mInstrumentation.callActivityOnCreate()

Activity.performCreate()

至此已經(jīng)回調(diào)到了Activity的onCreate()方法,Activity也就正式啟動了,后續(xù)就是對應(yīng)的聲明周期回調(diào)。

新聞名稱:flutterndk的簡單介紹
文章轉(zhuǎn)載:http://chinadenli.net/article31/dsgigpd.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站做網(wǎng)站網(wǎng)站設(shè)計公司虛擬主機標(biāo)簽優(yōu)化品牌網(wǎng)站制作

廣告

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

成都定制網(wǎng)站建設(shè)