02-Understanding VSYNC理解VSYNC

為了理解App是如何進(jìn)行渲染的吼旧,我們必須了解手機(jī)硬件是如何工作毡惜,那么就必須理解什么是VSYNC澎埠。

在講解VSYNC之前捣炬,我們需要了解兩個(gè)相關(guān)的概念:

Refresh Rate:代表了屏幕在一秒內(nèi)刷新屏幕的次數(shù),這取決于硬件的固定參數(shù)仪壮,例如60Hz憨颠。

Frame Rate:代表了GPU在一秒內(nèi)繪制操作的幀數(shù),例如30fps积锅,60fps爽彤。

GPU會(huì)獲取圖形數(shù)據(jù)進(jìn)行渲染,然后硬件負(fù)責(zé)把渲染后的內(nèi)容呈現(xiàn)到屏幕上缚陷,他們兩者不停的進(jìn)行協(xié)作适篙。

不幸的是,刷新頻率和幀率并不是總能夠保持相同的節(jié)奏箫爷。如果發(fā)生幀率與刷新頻率不一致的情況嚷节,就會(huì)容易出現(xiàn)Tearing的現(xiàn)象(畫面上下兩部分顯示內(nèi)容發(fā)生斷裂聂儒,來(lái)自不同的兩幀數(shù)據(jù)發(fā)生重疊)。

理解圖像渲染里面的雙重與三重緩存機(jī)制硫痰,這個(gè)概念比較復(fù)雜衩婚,請(qǐng)移步查看這里:http://source.android.com/devices/graphics/index.html,還有這里http://article.yeeyan.org/view/37503/304664效斑。

通常來(lái)說(shuō)非春,幀率超過刷新頻率只是一種理想的狀況,在超過60fps的情況下缓屠,GPU所產(chǎn)生的幀數(shù)據(jù)會(huì)因?yàn)榈却齎SYNC的刷新信息而被Hold住奇昙,這樣能夠保持每次刷新都有實(shí)際的新的數(shù)據(jù)可以顯示。但是我們遇到更多的情況是幀率小于刷新頻率敌完。

在這種情況下储耐,某些幀顯示的畫面內(nèi)容就會(huì)與上一幀的畫面相同。糟糕的事情是蠢挡,幀率從超過60fps突然掉到60fps以下弧岳,這樣就會(huì)發(fā)生LAGJANK业踏,HITCHING等卡頓掉幀的不順滑的情況。這也是用戶感受不好的原因所在涧卵。

Project Buffer背景介紹

隨著時(shí)間的推移勤家,AndroidOS系統(tǒng)一直在不斷進(jìn)化、壯大柳恐,日趨完善伐脖。但直到Android 4.0問世,有關(guān)UI顯示不流暢的問題也一直未得到根本解決乐设。在整個(gè)進(jìn)化過程中讼庇,Android在Display(顯示)系統(tǒng)這塊也下了不少功夫,例如近尚,使用硬件加速等技術(shù)蠕啄,但本質(zhì)原因似乎和硬件關(guān)系并不大,因?yàn)閕Phone的硬件配置并不比那些價(jià)格相近的Android機(jī)器的硬件配置強(qiáng)戈锻,而iPhone UI的流暢性強(qiáng)卻是有目共睹的歼跟。

從Android 4.1(版本代號(hào)為Jelly Bean)開始,Android OS開發(fā)團(tuán)隊(duì)便力圖在每個(gè)版本中解決一個(gè)重要問題(這是不是也意味著Android OS在經(jīng)過幾輪大規(guī)模改善后格遭,開始進(jìn)入手術(shù)刀式的精加工階段呢哈街?)。作為嚴(yán)重影響Android口碑問題之一的UI流暢性差的問題拒迅,首先在Android 4.1版本中得到了有效處理骚秦。其解決方法就是本文要介紹的Project Butter她倘。

Project Butter對(duì)Android Display系統(tǒng)進(jìn)行了重構(gòu),引入了三個(gè)核心元素作箍,即VSYNC硬梁、Triple Buffer和Choreographer。其中蒙揣,VSYNC是理解Project Buffer的核心靶溜。VSYNC是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上已經(jīng)很早就廣泛使用的技術(shù)懒震。讀者可簡(jiǎn)單的把它認(rèn)為是一種定時(shí)中斷罩息。

接下來(lái),本文將圍繞VSYNC來(lái)介紹Android Display系統(tǒng)的工作方式[①]个扰。請(qǐng)注意瓷炮,后續(xù)討論將以Display為基準(zhǔn),將其劃分成16ms長(zhǎng)度的時(shí)間段递宅,在每一時(shí)間段中娘香,Display顯示一幀數(shù)據(jù)(相當(dāng)于每秒60幀)。時(shí)間段從1開始編號(hào)办龄。

首先是沒有VSYNC的情況烘绽,如圖1所示:

圖1 沒有VSYNC的繪圖過程

由圖1可知:

時(shí)間從0開始,進(jìn)入第一個(gè)16ms:Display顯示第0幀俐填,CPU處理完第一幀后安接,GPU緊接其后處理繼續(xù)第一幀。三者互不干擾英融,一切正常盏檐。

時(shí)間進(jìn)入第二個(gè)16ms:因?yàn)樵缭谏弦粋€(gè)16ms時(shí)間內(nèi),第1幀已經(jīng)由CPU驶悟,GPU處理完畢胡野。故Display可以直接顯示第1幀。顯示沒有問題痕鳍。但在本16ms期間硫豆,CPU和GPU卻并未及時(shí)去繪制第2幀數(shù)據(jù)(注意前面的空白區(qū)),而是在本周期快結(jié)束時(shí)额获,CPU/GPU才去處理第2幀數(shù)據(jù)够庙。

時(shí)間進(jìn)入第3個(gè)16ms,此時(shí)Display應(yīng)該顯示第2幀數(shù)據(jù)抄邀,但由于CPU和GPU還沒有處理完第2幀數(shù)據(jù)耘眨,故Display只能繼續(xù)顯示第一幀的數(shù)據(jù),結(jié)果使得第1幀多畫了一次(對(duì)應(yīng)時(shí)間段上標(biāo)注了一個(gè)Jank)境肾。

通過上述分析可知剔难,此處發(fā)生Jank的關(guān)鍵問題在于胆屿,為何第1個(gè)16ms段內(nèi),CPU/GPU沒有及時(shí)處理第2幀數(shù)據(jù)偶宫?原因很簡(jiǎn)單非迹,CPU可能是在忙別的事情(比如某個(gè)應(yīng)用通過sleep固定時(shí)間來(lái)實(shí)現(xiàn)動(dòng)畫的逐幀顯示),不知道該到處理UI繪制的時(shí)間了纯趋≡魇蓿可CPU一旦想起來(lái)要去處理第2幀數(shù)據(jù),時(shí)間又錯(cuò)過了吵冒!

為解決這個(gè)問題纯命,Project Buffer引入了VSYNC,這類似于時(shí)鐘中斷痹栖。結(jié)果如圖2所示:

圖2 引入VSYNC的繪制過程

由圖2可知亿汞,每收到VSYNC中斷,CPU就開始處理各幀數(shù)據(jù)揪阿。整個(gè)過程非常完美疗我。

不過,仔細(xì)琢磨圖2卻會(huì)發(fā)現(xiàn)一個(gè)新問題:圖2中南捂,CPU和GPU處理數(shù)據(jù)的速度似乎都能在16ms內(nèi)完成吴裤,而且還有時(shí)間空余,也就是說(shuō)溺健,CPU/GPU的FPS(幀率嚼摩,F(xiàn)rames Per Second)要高于Display的FPS。確實(shí)如此矿瘦。由于CPU/GPU只在收到VSYNC時(shí)才開始數(shù)據(jù)處理,故它們的FPS被拉低到與Display的FPS相同愿卒。但這種處理并沒有什么問題缚去,因?yàn)锳ndroid設(shè)備的Display FPS一般是60,其對(duì)應(yīng)的顯示效果非常平滑琼开。

如果CPU/GPU的FPS小于Display的FPS易结,會(huì)是什么情況呢?請(qǐng)看圖3:

圖3 CPU/GPU FPS較小的情況

由圖3可知:

在第二個(gè)16ms時(shí)間段柜候,Display本應(yīng)顯示B幀搞动,但卻因?yàn)镚PU還在處理B幀,導(dǎo)致A幀被重復(fù)顯示渣刷。

同理鹦肿,在第二個(gè)16ms時(shí)間段內(nèi),CPU無(wú)所事事辅柴,因?yàn)锳 Buffer被Display在使用箩溃。B Buffer被GPU在使用瞭吃。注意,一旦過了VSYNC時(shí)間點(diǎn)涣旨,CPU就不能被觸發(fā)以處理繪制工作了歪架。

為什么CPU不能在第二個(gè)16ms處開始繪制工作呢?原因就是只有兩個(gè)Buffer霹陡。如果有第三個(gè)Buffer的存在和蚪,CPU就能直接使用它,而不至于空閑烹棉。出于這一思路就引出了Triple Buffer攒霹。結(jié)果如圖4所示:

圖4? Triple Buffer的情況

由圖4可知:

第二個(gè)16ms時(shí)間段,CPU使用C Buffer繪圖峦耘。雖然還是會(huì)多顯示A幀一次剔蹋,但后續(xù)顯示就比較順暢了。

是不是Buffer越多越好呢辅髓?回答是否定的泣崩。由圖4可知,在第二個(gè)時(shí)間段內(nèi)洛口,CPU繪制的第C幀數(shù)據(jù)要到第四個(gè)16ms才能顯示矫付,這比雙Buffer情況多了16ms延遲。所以第焰,Buffer最好還是兩個(gè)买优,三個(gè)足矣。

介紹了上述背景知識(shí)后挺举,下文將分析Android Project Buffer的一些細(xì)節(jié)杀赢。

Project Buffer分析

上一節(jié)對(duì)VSYNC進(jìn)行了理論分析,其實(shí)也引出了Project Buffer的三個(gè)關(guān)鍵點(diǎn):

核心關(guān)鍵:需要VSYNC定時(shí)中斷湘纵。

Triple Buffer:當(dāng)雙Buffer不夠使用時(shí)脂崔,該系統(tǒng)可分配第三塊Buffer。

另外梧喷,還有一個(gè)非常隱秘的關(guān)鍵點(diǎn):即將繪制工作都統(tǒng)一到VSYNC時(shí)間點(diǎn)上砌左。這就是Choreographer的作用。Choreographer是一個(gè)極富詩(shī)意的詞铺敌,意為舞蹈編導(dǎo)汇歹。在它的統(tǒng)一指揮下,應(yīng)用的繪制工作都將變得井井有條偿凭。

下面來(lái)看Project Buffer實(shí)現(xiàn)的細(xì)節(jié)产弹。

2.1? SurfaceFlinger家族的改進(jìn)

首先被動(dòng)刀的是SurfaceFlinger家族成員。目標(biāo)是提供VSYNC中斷笔喉。相關(guān)類圖如圖5所示:

圖5? SurfaceFlinger中和VSYNC有關(guān)的類

由圖5可知:

HardwareComposer封裝了相關(guān)的HAL層取视,如果硬件廠商提供的HAL層實(shí)現(xiàn)能定時(shí)產(chǎn)生VSYNC中斷硝皂,則直接使用硬件的VSYNC中斷,否則HardwareComposer內(nèi)部會(huì)通過VSyncThread來(lái)模擬產(chǎn)生VSYNC中斷(其實(shí)現(xiàn)很簡(jiǎn)單,就是sleep固定時(shí)間,然后喚醒)识腿。

當(dāng)VSYNC中斷產(chǎn)生時(shí)(不管是硬件產(chǎn)生還是VSyncThread模擬的),VSyncHandler的onVSyncReceived函數(shù)將被調(diào)用贝或。所以,對(duì)VSYNC中斷來(lái)說(shuō)锐秦,VSyncHandler的onVSyncReceived咪奖,就是其中斷處理函數(shù)。

在SurfaceFlinger家族中酱床,VSyncHandler的實(shí)例是EventThread羊赵。下邊是EventThread類的聲明:

class EventThread : public Thread, public DisplayHardware::VSyncHandler

由EventThread定義可知,它本身運(yùn)行在一個(gè)單獨(dú)的線程中扇谣,并繼承了VSyncHandler昧捷。EventThread的核心處理在其線程函數(shù)threadLoop中完成,其處理邏輯主要是:

等待下一次VSYNC的到來(lái)罐寨,并派發(fā)該中斷事件給VSYNC監(jiān)聽者靡挥。

通過EventThread,VSYNC中斷事件可派發(fā)給多個(gè)該中斷的監(jiān)聽者去處理鸯绿。相關(guān)類如圖6所示:

圖6? EventThread和VSYNC中斷監(jiān)聽者

由圖6可知:

SurfaceFlinger從Thread派生跋破,其核心功能單獨(dú)運(yùn)行在一個(gè)線程中。

SurfaceFlinger包括一個(gè)EventThread和一個(gè)MessageQueue對(duì)象瓶蝴。

對(duì)象通過mEvents成員指向一個(gè)IDisplayEventConnection類型的對(duì)象毒返。IDisplayEventConnection是一個(gè)純虛類,它代表VSYNC中斷的監(jiān)聽者舷手。其實(shí)體類是EventThread的內(nèi)部類Connection饿悬。

IDisplayEventConnection定義了一個(gè)getDataChannel函數(shù),該函數(shù)返回一個(gè)BitTube實(shí)例聚霜。這個(gè)實(shí)例提供的read/write方法,用于傳送具體的信號(hào)數(shù)據(jù)(其內(nèi)部實(shí)現(xiàn)為socketpair珠叔,可通過Binder實(shí)現(xiàn)進(jìn)程跨越)蝎宇。

EventThread最重要的一個(gè)VSYNC監(jiān)聽者就是MessageQueue的mEvents對(duì)象。當(dāng)然祷安,這一切都是為最大的后臺(tái)老板SurfaceFlinger服務(wù)的姥芥。來(lái)自EventThread的VSYNC中斷信號(hào),將通過MessageQueue轉(zhuǎn)化為一個(gè)REFRESH消息并傳遞給SurfaceFlinger的onMessageReceived函數(shù)處理汇鞭。

有必要指出凉唐,4.1中SurfaceFlinger onMessageReceived函數(shù)的實(shí)現(xiàn)僅僅是將4.0版本的SurfaceFlinger的核心函數(shù)挪過來(lái)罷了[②]庸追,并未做什么改動(dòng)。

以上是Project Buffer對(duì)SurfaceFlinger所做的一些改動(dòng)台囱。那么Triple Buffer是怎么處理的呢淡溯?幸好從Android 2.2開始,Display的Page Flip算法就不依賴Buffer的個(gè)數(shù)簿训,Buffer個(gè)數(shù)不過是算法的一個(gè)參數(shù)罷了咱娶。所以,Triple Buffer的引入强品,只是把Buffer的數(shù)目改成了3膘侮,而算法本身相對(duì)于4.0來(lái)說(shuō)并沒有變化。圖7為Triple Buffer的設(shè)置示意圖:

圖7? Layer.cpp中對(duì)Triple Buffer的設(shè)置

圖7所示的榛,為L(zhǎng)ayer.cpp中對(duì)Buffer個(gè)數(shù)的設(shè)置琼了。TARGET_DISABLE_TRIPLE_BUFFERING宏可設(shè)置Buffer的個(gè)數(shù)。對(duì)某些內(nèi)存/顯存并不是很大的設(shè)備夫晌,也可以選擇不使用Triple Buffer。

2.2? Choreographer介紹

Choreographer是一個(gè)Java類慷丽。第一次看到這個(gè)詞時(shí),我很激動(dòng)要糊。一個(gè)小小的命名真的反應(yīng)出了設(shè)計(jì)者除coding之外的廣博的視界。試想局劲,如果不是對(duì)舞蹈有相當(dāng)了解或喜愛,一般人很難想到用這個(gè)詞來(lái)描述它鱼填。

Choreographer的定義和基本結(jié)構(gòu)如圖8所示:

圖8? Choreographer的定義和結(jié)構(gòu)

圖8中:

Choreographer是線程單例的毅戈,而且必須要和一個(gè)Looper綁定,因?yàn)槠鋬?nèi)部有一個(gè)Handler需要和Looper綁定苇经。

DisplayEventReceiver是一個(gè)abstract class,其JNI的代碼部分會(huì)創(chuàng)建一個(gè)IDisplayEventConnection的VSYNC監(jiān)聽者對(duì)象扇单。這樣,來(lái)自EventThread的VSYNC中斷信號(hào)就可以傳遞給Choreographer對(duì)象了施流。由圖8可知响疚,當(dāng)VSYNC信號(hào)到來(lái)時(shí)瞪醋,DisplayEventReceiver的onVsync函數(shù)將被調(diào)用。

另外趟章,DisplayEventReceiver還有一個(gè)scheduleVsync函數(shù)。當(dāng)應(yīng)用需要繪制UI時(shí)宏侍,將首先申請(qǐng)一次VSYNC中斷,然后再在中斷處理的onVsync函數(shù)去進(jìn)行繪制谅河。

Choreographer定義了一個(gè)FrameCallback interface,每當(dāng)VSYNC到來(lái)時(shí)绷耍,其doFrame函數(shù)將被調(diào)用鲜侥。這個(gè)接口對(duì)Android Animation的實(shí)現(xiàn)起了很大的幫助作用褂始。以前都是自己控制時(shí)間描函,現(xiàn)在終于有了固定的時(shí)間中斷。

Choreographer的主要功能是舀寓,當(dāng)收到VSYNC信號(hào)時(shí),去調(diào)用使用者通過postCallback設(shè)置的回調(diào)函數(shù)必尼。目前一共定義了三種類型的回調(diào),它們分別是:

CALLBACK_INPUT:優(yōu)先級(jí)最高判莉,和輸入事件處理有關(guān)育谬。

CALLBACK_ANIMATION:優(yōu)先級(jí)其次骂租,和Animation的處理有關(guān)斑司。

CALLBACK_TRAVERSAL:優(yōu)先級(jí)最低,和UI等控件繪制有關(guān)宿刮。

優(yōu)先級(jí)高低和處理順序有關(guān)。當(dāng)收到VSYNC中斷時(shí)胡桃,Choreographer將首先處理INPUT類型的回調(diào),然后是ANIMATION類型翠胰,最后才是TRAVERSAL類型自脯。

此外之景,讀者在自行閱讀Choreographer相關(guān)代碼時(shí)膏潮,還會(huì)發(fā)現(xiàn)Android對(duì)Message/Looper類[③]也進(jìn)行了一番小改造,使之支持Asynchronous Message和Synchronization Barrier(參照Looper.java的postSyncBarrier函數(shù))焕参。其實(shí)現(xiàn)非常巧妙,這部分內(nèi)容就留給讀者自己理解并欣賞了刻帚。

相比SurfaceFlinger涩嚣,Choreographer是Android 4.1中的新事物崇众,下面將通過一個(gè)實(shí)例來(lái)簡(jiǎn)單介紹Choreographer的工作原理缓艳。

假如UI中有一個(gè)控件invalidate了,那么它將觸發(fā)ViewRootImpl的invalidate函數(shù)阶淘,該函數(shù)將最終調(diào)用ViewRootImpl的scheduleTraversals。其代碼如圖9所示:

圖9? ViewRootImpl scheduleTraversals函數(shù)的實(shí)現(xiàn)

由圖9可知坤塞,scheduleTraversals首先禁止了后續(xù)的消息處理功能澈蚌,這是由設(shè)置Looper的postSyncBarrier來(lái)完成的摹芙。一旦設(shè)置了SyncBarrier宛瞄,所有非Asynchronous的消息便將停止派發(fā)。

然后,為Choreographer設(shè)置了CALLBACK類型為TRAVERSAL的處理對(duì)象蝴簇,即mTraversalRunnable匆帚。

最后調(diào)用scheduleConsumeBatchedInput熬词,這個(gè)函數(shù)將為Choreographer設(shè)置了CALLBACK類型為INPUT的處理對(duì)象吸重。

Choreographer的postCallback函數(shù)將會(huì)申請(qǐng)一次VSYNC中斷(通過調(diào)用DisplayEventReceiver的scheduleVsync實(shí)現(xiàn))。當(dāng)VSYNC信號(hào)到達(dá)時(shí)颜矿,Choreographer doFrame函數(shù)被調(diào)用,內(nèi)部代碼會(huì)觸發(fā)回調(diào)處理或衡。代碼片段如圖10所示:

圖10? Choreographer doFrame函數(shù)片段

對(duì)ViewRootImpl來(lái)說(shuō)车遂,其TRAVERSAL回調(diào)對(duì)應(yīng)的處理對(duì)象,就是前面介紹的mTraversalRunnable舶担,它的代碼很簡(jiǎn)單,如圖11所示:

圖11 ?mTraversalRunnable的實(shí)現(xiàn)

doTraversal內(nèi)部實(shí)現(xiàn)和Android 4.0版本一致柄瑰。故相比于4.0來(lái)說(shuō),4.1只是把doTraversal調(diào)用位置放到VSYNC中斷處理中了教沾。

通過上邊的介紹译断,可知Choreographer確實(shí)做到了對(duì)繪制工作的統(tǒng)一安排授翻,不愧是個(gè)長(zhǎng)于統(tǒng)籌安排的“舞蹈編導(dǎo)”孙咪。


參考資料

Android性能優(yōu)化典范 - 第1季

Android Project Butter分析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市淮菠,隨后出現(xiàn)的幾起案子荤堪,更是在濱河造成了極大的恐慌合陵,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糠爬,死亡現(xiàn)場(chǎng)離奇詭異举庶,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)户侥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門峦嗤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人烁设,你說(shuō)我怎么就攤上這事∽昂冢” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵糠睡,是天一觀的道長(zhǎng)疚颊。 經(jīng)常有香客問我,道長(zhǎng)材义,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任其掂,我火速辦了婚禮,結(jié)果婚禮上喘漏,老公的妹妹穿的比我還像新娘。我一直安慰自己翩迈,他們只是感情好盔夜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布堤魁。 她就那樣靜靜地躺著返十,像睡著了一般妥泉。 火紅的嫁衣襯著肌膚如雪洞坑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天刽沾,我揣著相機(jī)與錄音,去河邊找鬼侧漓。 笑死监氢,一個(gè)胖子當(dāng)著我的面吹牛布蔗,可吹牛的內(nèi)容都是我干的浪腐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼骡男,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼傍睹!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拾稳,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎访得,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悍抑,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年拂盯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了记靡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谈竿。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡空凸,死狀恐怖嚎花,靈堂內(nèi)的尸體忽然破棺而出呀洲,到底是詐尸還是另有隱情,我是刑警寧澤道逗,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響仿荆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拢操,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一令境、第九天 我趴在偏房一處隱蔽的房頂上張望杠园。 院中可真熱鬧舔庶,春花似錦、人聲如沸惕橙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至朦促,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間务冕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工混滔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洒疚,地道東北人歹颓。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓油湖,卻偏偏與公主長(zhǎng)得像巍扛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乏德,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 本篇文章是基于谷歌有關(guān)Graphic的一篇概覽文章的翻譯:http://source.android.com/de...
    lee_3do閱讀 7,123評(píng)論 2 21
  • 3.2 Android顯示原理 Android應(yīng)用程序的顯示過程包含了兩個(gè)部分(應(yīng)用側(cè)繪制撤奸、系統(tǒng)側(cè)渲染)、兩個(gè)機(jī)制...
    jianhuih閱讀 2,598評(píng)論 1 6
  • 總結(jié)Android渲染部分的工作原理喊括,其中參考了如下網(wǎng)址:http://www.androidpolice.com...
    xuluqxulu閱讀 4,836評(píng)論 0 54
  • 今天聽到群里的朋友在問群里小朋友們一個(gè)問題“帶的是高中生府喳。不管怎么付出,他們?nèi)耘f無(wú)所謂蘑拯。若遇到這種情況钝满,你...
    班卓閱讀 821評(píng)論 0 3
  • 張宇 雨一直下 氣氛不算融洽 在同個(gè)屋檐下 你漸漸感到心在變化 你愛著他 也許也帶著恨吧 青春耗了一...
    博安吉閱讀 383評(píng)論 0 0