Android圖形顯示系統(tǒng)(一)

轉(zhuǎn)載請注明出處:http://blog.csdn.net/a740169405/article/details/70548443

簡介

本文講解的內(nèi)容是Android4.1以后的系統(tǒng)機(jī)制酱固,將從整體上分析Android圖形顯示系統(tǒng)的結(jié)構(gòu)腻暮,不深入分析每一層內(nèi)部的代碼實(shí)現(xiàn)般妙,更多的是使用流程圖和結(jié)構(gòu)圖來讓大家理解Android是如何繪制、合成圖形并顯示到屏幕上裳擎。

本文將從三個(gè)層次進(jìn)行講解,大致如下圖:


大體流程

可以理解為上層生產(chǎn)骆莹,下層消費(fèi)模型仪召。

其中每一層之間的數(shù)據(jù)傳遞是使用Buffer(圖形緩沖區(qū))作為載體:


圖形數(shù)據(jù)的載體

這里的緩沖區(qū),大家可以理解為帶有寬高和像素密度的內(nèi)存區(qū)塊雨膨。

1. 從下層往上層理解

1.1 顯示屏

顯示屏上的內(nèi)容擂涛,是從硬件幀緩沖區(qū)讀取的,大致讀取過程為:從Buffer的起始地址開始聊记,從上往下撒妈,從左往右掃描整個(gè)Buffer,將內(nèi)容映射到顯示屏上:


屏幕與幀緩沖區(qū)關(guān)系圖1

當(dāng)然排监,屏幕上的內(nèi)容需要需要不斷的更新狰右,如果在同一個(gè)Buffer進(jìn)行讀取和寫入(合成)操作,將會導(dǎo)致屏幕顯示多幀內(nèi)容舆床。所以硬件層除了提供一個(gè)Buffer用于屏幕顯示棋蚌,還提供了一個(gè)Buffer用于后臺的圖形合成嫁佳,也就是我們常說的雙緩沖:

屏幕與幀緩沖區(qū)關(guān)系圖2

上圖中包含兩個(gè)緩沖區(qū):
前緩沖區(qū):用來顯示內(nèi)容到屏幕的幀緩沖區(qū)
后緩沖區(qū):用于后臺合成下一幀圖形的幀緩沖區(qū)

假設(shè)前一幀顯示完畢,后一幀準(zhǔn)備好了谷暮,屏幕將會開始讀取下一幀的內(nèi)容蒿往,也就是開始讀取上圖中的后緩沖區(qū)的內(nèi)容:


屏幕與幀緩沖區(qū)關(guān)系圖途2

此時(shí),前后緩沖區(qū)進(jìn)行一次角色互換湿弦,之前的后緩沖區(qū)變?yōu)榍熬彌_區(qū)熄浓,進(jìn)行圖形的顯示,之前的前緩沖區(qū)則變?yōu)楹缶彌_區(qū)省撑,進(jìn)行圖形的合成赌蔑。

然而,理想很豐滿竟秫,現(xiàn)實(shí)很骨感娃惯,上面假設(shè)“當(dāng)前一幀顯示完畢,后一幀準(zhǔn)備好了”的情況肥败,在現(xiàn)實(shí)中這兩個(gè)事件并非同時(shí)完成趾浅。那么,屏幕掃描緩沖區(qū)的速度和系統(tǒng)合成幀的速度之間有什么關(guān)系呢馒稍,帶著這個(gè)疑惑我們看看下面兩個(gè)概念:
屏幕刷新率(HZ):代表屏幕在一秒內(nèi)刷新屏幕的次數(shù)皿哨,Android手機(jī)一般為60HZ(也就是1秒刷新60幀,大約16.67毫秒刷新1幀)
系統(tǒng)幀速率(FPS):代表了系統(tǒng)在一秒內(nèi)合成的幀數(shù)纽谒,該值的大小由系統(tǒng)算法和硬件決定证膨。

我們用以下兩個(gè)假設(shè)來分析兩者的關(guān)系:
① 屏幕刷新速率比系統(tǒng)幀速率快
此時(shí),在前緩沖區(qū)內(nèi)容全部映射到屏幕上之后鼓黔,后緩沖區(qū)尚未準(zhǔn)備好下一幀央勒,屏幕將無法讀取下一幀,所以只能繼續(xù)顯示當(dāng)前一幀的圖形澳化,造成一幀顯示多次崔步,也就是卡頓。
② 系統(tǒng)幀速率比屏幕刷新率快
此時(shí)缎谷,屏幕未完全把前緩沖區(qū)的一幀映射到屏幕井濒,而系統(tǒng)已經(jīng)在后緩沖區(qū)準(zhǔn)備好了下一幀,并要求讀取下一幀到屏幕列林,將會導(dǎo)致屏幕上半部分是上一幀的圖形瑞你,而下半部分是下一幀的圖形,造成屏幕上顯示多幀席纽,也就是屏幕撕裂捏悬。

上面兩種情況,都會導(dǎo)致問題润梯,根本原因就是兩個(gè)緩沖區(qū)的操作速率不一致过牙,解決辦法就是讓屏幕控制前后緩沖區(qū)的切換甥厦,讓系統(tǒng)幀速率配合屏幕刷新率的節(jié)奏。

那么屏幕是如何控制這個(gè)節(jié)奏的呢寇钉?

垂直同步(VSync):當(dāng)屏幕從緩沖區(qū)掃描完一幀到屏幕上之后刀疙,開始掃描下一幀之前,發(fā)出的一個(gè)同步信號扫倡,該信號用來切換前緩沖區(qū)和后緩沖區(qū)谦秧。

通過上面的分析可以看出,屏幕的顯示節(jié)奏是固定的撵溃,操作系統(tǒng)需要配合屏幕的顯示疚鲤,在固定的時(shí)間內(nèi)準(zhǔn)備好下一幀,以供屏幕進(jìn)行顯示缘挑。兩者通過VSync信號來實(shí)現(xiàn)同步集歇。

關(guān)于屏幕這一塊的知識點(diǎn)講解到這,不再深入分析语淘,接下來我們將會了解后緩沖區(qū)的圖形合成者诲宇。

1.2 SurfaceFlinger-圖形合成者

如果說屏幕是消費(fèi)者,那么SurfaceFlinger相對屏幕來說就是生產(chǎn)者惶翻,其具有如下特性:

  • 作為上層應(yīng)用的消費(fèi)者姑蓝,硬件層的生產(chǎn)者。
  • 負(fù)責(zé)圖形的合成
  • 和ActivityManagerService一樣吕粗,是一個(gè)系統(tǒng)服務(wù)

為了更好的理解SurfaceFlinger這個(gè)服務(wù)的工作內(nèi)容纺荧,以及他是如何做到一個(gè)承上啟下的作用,我們通過下面的這個(gè)界面分析:


這里寫圖片描述

界面很簡單溯泣,拆開來看虐秋,包含微信榕茧、懸浮工具箱垃沦、通知欄、底部虛擬按鍵欄:


界面對應(yīng)的surface

我們可以先這樣理解上面這幅圖用押,上層每一個(gè)界面肢簿,其實(shí)都對應(yīng)SufaceFlinger里的一個(gè)Surface對象,上層將自己的內(nèi)容繪制在對應(yīng)的Surface內(nèi)蜻拨,接著池充,SufaceFlinger需要將所有上層對應(yīng)的Surface內(nèi)的圖形進(jìn)行合成,具體看下圖:


SurfaceFlinger合成過程

沒錯(cuò)缎讼,SurfaceFlinger就是將多個(gè)Surface里的內(nèi)容進(jìn)行合成收夸,最后提交到屏幕的后緩沖區(qū),等待屏幕的下一個(gè)垂直同步信號的到來血崭,再顯示到屏幕上卧惜。

我們會發(fā)現(xiàn)SufaceFlinger通過屏幕后緩沖區(qū)與屏幕建立聯(lián)系厘灼。同時(shí)通過Surface與上層建立聯(lián)系。從而起到一個(gè)承上啟下的作用咽瓷,是Android圖形系統(tǒng)結(jié)構(gòu)中的關(guān)鍵組成部分设凹。

為了繼續(xù)往上層講,我們需要了解什么是Surface:

  • 對應(yīng)上層的一個(gè)Window(對話框茅姜、Activity闪朱、狀態(tài)欄)
  • 作為上層圖形繪制的畫板
  • Canvas是畫筆,上層通過調(diào)用Canvas的API向Surface上繪制圖形
  • Surface內(nèi)部存在多個(gè)緩沖區(qū)钻洒,形成一個(gè)BufferQueue

如果說SurfaceFinger是圖形的合成者奋姿,那么圖形的提供者就是上層。文章一開始就提到素标,圖形的傳遞是通過Buffer作為載體胀蛮,Surface是對Buffer的進(jìn)一步封裝,也就是說Surface內(nèi)部具有多個(gè)Buffer供上層使用糯钙,如何管理這些Buffer呢粪狼?請看下面這個(gè)模型:


BufferQueue

Surface內(nèi)部提供一個(gè)BufferQueue,與上層和SurfaceFlinger形成一個(gè)生產(chǎn)者消費(fèi)者模型任岸,上層對應(yīng)Producer再榄,SurfaceFlinger對應(yīng)Consumer。三者通過Buffer產(chǎn)生聯(lián)系享潜,每個(gè)Buffer都有四種狀態(tài):

  • Free:可被上層使用
  • Dequeued:出列困鸥,正在被上層使用
  • Queued:入列,已完成上層繪制剑按,等待SurfaceFlinger合成
  • Acquired:被獲取疾就,SurfaceFlinger正持有該Buffer進(jìn)行合成

Buffer的一次轉(zhuǎn)移過程大致為:

  1. 從BufferQueue轉(zhuǎn)移到上層
  2. 上層繪制完成再放回BufferQueue
  3. 接著SurfaceFlinger再拿去合成
  4. 最后又放回BufferQueue

如此循環(huán),形成一個(gè)Buffer被循環(huán)使用的過程艺蝴。

關(guān)于SurfaceFlinger以及SurfaceFlinger與上層建立聯(lián)系的Surface講解完了猬腰,接下來看看上層是如何將圖形繪制到Surface的Buffer中。

1.3 上層繪圖

上層繪圖的大體流程見下圖:


上層繪圖

?之前有說到猜敢,Surface里的Buffer作為上層的畫板姑荷,Canvas作為畫筆,通過調(diào)用Canvas的API完成圖形的繪制缩擂,上層通過調(diào)用draw方法來調(diào)用Canvas的API鼠冕,當(dāng)然這里的draw方法并沒有真正的將圖形繪制到緩沖區(qū),而是記錄了一下繪制命令胯盯,具體需要了解DisplayList相關(guān)只是懈费,后面會對其進(jìn)行分析。

從流程上看:

  1. 測量View的寬高(Measure)
  2. 設(shè)置View的寬高位置(Layout)
  3. 創(chuàng)建顯示列表博脑,并執(zhí)行繪制(Draw)
  4. 生成多邊形和紋理
  5. 對多邊形和紋理進(jìn)行柵格化操作

從執(zhí)行者的角度看:

  1. CPU:Measure憎乙,Layout薄坏,紋理和多邊形生成,發(fā)送紋理和多邊形到GPU
  2. GPU:將CPU生成的紋理和多邊形進(jìn)行柵格化以及合成

上面說的的紋理和多邊形還有柵格化以及合成寨闹,這里不做具體的講解胶坠,需要了解的是圖形的繪制流程需要經(jīng)過這些操作。從上面的分析可以看出繁堡,上層繪制圖形時(shí)需要經(jīng)過CPU計(jì)算沈善,再經(jīng)過GPU計(jì)算。

經(jīng)過上面的分析椭蹄,整個(gè)Android的圖形繪制大體流程已經(jīng)分析完成闻牡,接下來將會分析一些流程的具體實(shí)現(xiàn),分析的內(nèi)容包括:

  • Android 4.1 加入的VSync信號同步到上層以及三緩沖
  • 從上層往下層具體分析每一步流程

2. VSync以及三緩沖

2.1 Drawing Without VSync

?從上面的講解可以看出绳矩,整個(gè)繪制流程的節(jié)奏罩润,分成兩個(gè)生產(chǎn)者消費(fèi)者模型,一個(gè)由屏幕和SurfaceFlinger構(gòu)成翼馆,另一個(gè)由SurfaceFlinger和上層應(yīng)用構(gòu)成割以,具體流程可以用下圖來描述:


drawing without vsync

其中:

  1. CPU和GPU代表上層的繪制執(zhí)行者
  2. Composite代表的是SurfaceFlinger對多個(gè)Surface的合成
  3. Background Buffer和Front Buffer分別代表的是硬件幀緩沖區(qū)中的前緩沖和后緩沖
  4. 顯示屏掃描完一幀之后,會發(fā)出VSync信號來切換并顯示下一幀

上面的流程中应媚,存在一個(gè)問題严沥,屏幕的VSync信號只是用來控制幀緩沖區(qū)的切換,并未控制上層的繪制節(jié)奏中姜,也就是說上層的生產(chǎn)節(jié)奏和屏幕的顯示節(jié)奏是脫離的:


drawing without vsync

上圖中消玄,橫軸表示時(shí)間,縱軸表示Buffer的使用者丢胚,每個(gè)長方形表示Buffer的使用翩瓜,長方形的寬度代表使用時(shí)長,VSync代表垂直同步信號携龟,兩個(gè)VSync信號之間間隔16.6ms兔跌。此圖描述了Android在4.1系統(tǒng)版本之前,上層的繪圖流程在沒有VSync信號的時(shí)候骨宠,出現(xiàn)的繪制問題浮定。

我們從時(shí)間為0開始看,當(dāng)前屏幕顯示第0幀层亿,上層CPU開始計(jì)算第1幀的紋理,計(jì)算完成后立美,交由GPU進(jìn)行柵格化匿又。當(dāng)下一個(gè)垂直同步信號到來,屏幕顯示下一幀建蹄,這時(shí)候碌更,上層CPU并未馬上開始準(zhǔn)備下一幀裕偿,而當(dāng)CPU開始準(zhǔn)備下一幀的時(shí)候已經(jīng)太晚了,下一個(gè)VSync信號來臨的時(shí)候晒哄,GPU未能繪制完第二幀的處理脯燃,導(dǎo)致屏幕再次顯示上一幀畅哑,造成卡頓:


drawing without vsync

2.2 Drawing With VSync

因?yàn)樯蠈硬恢繴Sync信號已經(jīng)發(fā)出,導(dǎo)致上層未能開始CPU的計(jì)算鸟妙。google在Android 4.1系統(tǒng)中加入了上層接收垂直同步信號的邏輯,大致流程如下:


draw with vsync

也就是說挥吵,屏幕在顯示完一幀后重父,發(fā)出的垂直同步除了通知幀緩沖區(qū)的切換之外,該消息還會發(fā)送到上層忽匈,通知上層開始繪制下一幀房午。

那么,上層是如何接受這個(gè)VSync消息的呢丹允?

2.2.1 Choreographer VSync信號的上層接收者

Google為上層設(shè)計(jì)了一個(gè)Choreographer類郭厌,翻譯成中文是“編舞者”,是希望通過它來控制上層的繪制(舞蹈)節(jié)奏雕蔽。

首先看看Choreographer的類圖:


Choreographer類圖

可以發(fā)現(xiàn)沪曙,Choreographer需要向SurfaceFlinger來注冊一個(gè)VSync信號的接收器DisplayEventReceiver。同時(shí)在Choreographer的內(nèi)部維護(hù)了一個(gè)CallbackQueue萎羔,用來保存上層關(guān)心VSync信號的組件液走,包括ViewRootImpl,TextView贾陷,ValueAnimator等缘眶。

再看看上層接收VSync的時(shí)序圖:


上層接收VSync時(shí)序圖

知道了Choreographer是上層用來接收VSync的角色之后,我們需要進(jìn)一步了解VSync信號是如何控制上層的繪制的:


上層VSync與繪制相結(jié)合的時(shí)序圖

一般髓废,上層需要繪制新的UI都是因?yàn)閂iew的requestLayout或者是invalidate方法被調(diào)用觸發(fā)的巷懈,我們以這個(gè)為起點(diǎn),跟蹤上層View的繪制流程:

  1. requestLayout或者invalidate觸發(fā)更新視圖請求
  2. 更新請求傳遞到ViewRootImpl中慌洪,ViewRootImpl向主線程MessageQueue中加入一個(gè)阻塞器顶燕,該阻塞器將會攔截所有同步消息,也就是說此時(shí)冈爹,我們再通過Handler向主線程MessageQueue發(fā)送的所有Message都將無法被執(zhí)行涌攻。
  3. ViewRootImpl向Choreographer注冊下一個(gè)VSync信號
  4. Choreographer通過DisplayEventReceiver向framework層注冊下一個(gè)VSync信號
  5. 當(dāng)?shù)讓赢a(chǎn)生下一個(gè)VSync消息時(shí),該信號將會發(fā)送給DisplayEventReceiver频伤,最后傳遞給Choreographer
  6. Choreographer收到VSync信號之后恳谎,向主線程MessageQueue發(fā)送了一個(gè)異步消息,我們在第二步提到,ViewRootImpl向MessageQueue發(fā)送了一個(gè)同步消息阻塞器因痛。這里Choreographer發(fā)送的異步消息婚苹,是不會被阻塞器攔截的。
  7. 最后鸵膏,異步消息的執(zhí)行者是ViewRootImpl膊升,也就是真正開始繪制下一幀了

至此,底層的VSync控制上層的邏輯就解釋完了谭企,此時(shí)上層繪制圖形的流程與VSync信號的關(guān)系可以用下圖表示:


draw with vsync

時(shí)間從屏幕顯示第0幀開始廓译,CPU開始準(zhǔn)備第1幀圖形的處理,好了之后交給GPU進(jìn)行處理赞咙,在上層收到下一個(gè)VSync之后责循,CPU立馬開始第2幀的處理,上層繪圖的節(jié)奏就和VSync信號保持一致了攀操,整個(gè)繪圖非常流暢院仿。

然而,理想很豐滿速和,現(xiàn)實(shí)很骨感歹垫,如果CPU和GPU沒能在下一個(gè)VSync信號到來之前完成下一幀的繪制工作,又會是怎么樣的呢颠放?


parallel processing and double buffering

還是從屏幕顯示第A幀開始排惨,時(shí)間進(jìn)入第一個(gè)16.6ms,CPU和GPU合成第B幀碰凶,當(dāng)下一個(gè)VSync信號到來的時(shí)候暮芭,GPU未能及時(shí)完成第B幀的繪制,此時(shí)欲低,GPU占有一個(gè)Surface里的Buffer辕宏,而同時(shí)SurfaceFlinger又持有一個(gè)Buffer用于合成顯示下一幀到屏幕,這樣的話砾莱,就導(dǎo)致Surface里的兩個(gè)緩沖區(qū)都被占用了瑞筐。此時(shí)SurfaceFlinger只能使用第A幀已經(jīng)準(zhǔn)備好的Buffer來合成,GPU繼續(xù)在另一個(gè)緩沖區(qū)中合成第B幀腊瑟,此時(shí)CPU無法開始下一幀的合成聚假,因?yàn)榫彌_區(qū)用完了。另外一個(gè)不好的事情是CPU只有在VSync信號來的時(shí)候才開始繪制下一幀闰非,也是就是說在第二個(gè)16.6ms時(shí)間內(nèi)膘格,CPU一直處于空閑狀態(tài),未進(jìn)行下一幀的計(jì)算河胎。
只有等到第二個(gè)VSync信號來了之后闯袒,CPU才開始在繪制下一幀。如果CPU和GPU需要合成的圖形太多游岳,將會導(dǎo)致連續(xù)性的卡頓政敢,如果CPU和GPU大部分時(shí)候都無法在16.6ms完成一幀的繪制,將會導(dǎo)致連續(xù)的卡頓現(xiàn)象胚迫。

別著急喷户,請看看Google的決絕方案。

2.3 parallel processing and triple buffering

沒錯(cuò)访锻,就是加入第三個(gè)Buffer褪尝,CPU和GPU還有SurfaceFlinger各占一個(gè)Buffer,并行處理圖形:


parallel processing and triple buffering

從上圖可以看出期犬,在第一個(gè)VSync到來時(shí)河哑,盡管SurfaceFlinger占了一個(gè)Buffer,GPU又占了一個(gè)Buffer龟虎,CPU仍然可以在第三個(gè)Buffer中開始下一幀的計(jì)算璃谨,整個(gè)顯示過程就開始時(shí)卡頓了一幀,之后都是流暢的鲤妥。

當(dāng)然系統(tǒng)并非一直開啟三個(gè)Buffer佳吞,因?yàn)锽uffer是需要消耗資源的,并且棉安,我們會發(fā)現(xiàn)底扳,上圖中,GPU處理好的圖形贡耽,需要跨越兩個(gè)VSync信號衷模,才能顯示。這樣的話蒲赂,給用戶的影響是一個(gè)延遲的現(xiàn)象阱冶。

為了解決該問題,我們需要再次從上層往下層了解Android繪制圖形的各個(gè)細(xì)節(jié)凳宙,并進(jìn)行優(yōu)化熙揍。對于應(yīng)用程序開發(fā)人員來說,重點(diǎn)還是上層的優(yōu)化氏涩,對自己的應(yīng)用程序的內(nèi)存届囚,UI,數(shù)據(jù)等進(jìn)行優(yōu)化是尖。

總結(jié):

  • Android通過Buffer來保存圖形信息意系,為了讓圖形顯示的更加流程,在提供一一個(gè)Buffer用于顯示的同時(shí)饺汹,開辟一個(gè)或者多個(gè)Buffer用于后臺圖形的合成蛔添。
  • Android4.1之前,VSync信號并未傳遞給上層,導(dǎo)致生產(chǎn)與消費(fèi)節(jié)奏不統(tǒng)一
  • Android4.1之后迎瞧,上層開始繪制時(shí)機(jī)都放到了VSync信號的到來時(shí)候
  • 除了在上層引入VSync機(jī)制夸溶,Anroid在4.1還加入了三緩沖,用來減少卡頓的產(chǎn)生
  • 每個(gè)Surface都有自己的繪制流程凶硅,需要先經(jīng)過CPU處理缝裁,再經(jīng)過GPU處理,之后經(jīng)過SurfaceFlinger與其他Surface繪制好的圖形和合成在一起足绅,供屏幕顯示
  • VSync信號貫穿整個(gè)繪制流程捷绑,控制著整個(gè)Android圖形系統(tǒng)的節(jié)奏

以上內(nèi)容可能有不對的地方,希望各路大神指教氢妈,下一篇文章將從上層往下層講解Android的圖形顯示流程粹污,并把上層的圖形繪制流程展開講解,敬請期待首量!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壮吩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蕾总,更是在濱河造成了極大的恐慌粥航,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件生百,死亡現(xiàn)場離奇詭異递雀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蚀浆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門缀程,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人市俊,你說我怎么就攤上這事杨凑。” “怎么了摆昧?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵撩满,是天一觀的道長。 經(jīng)常有香客問我绅你,道長伺帘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任忌锯,我火速辦了婚禮伪嫁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘偶垮。我一直安慰自己张咳,他們只是感情好帝洪,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脚猾,像睡著了一般葱峡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婚陪,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天族沃,我揣著相機(jī)與錄音频祝,去河邊找鬼泌参。 笑死,一個(gè)胖子當(dāng)著我的面吹牛常空,可吹牛的內(nèi)容都是我干的沽一。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼漓糙,長吁一口氣:“原來是場噩夢啊……” “哼铣缠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起昆禽,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蝗蛙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后醉鳖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捡硅,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年盗棵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了壮韭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纹因,死狀恐怖喷屋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瞭恰,我是刑警寧澤屯曹,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站惊畏,受9級特大地震影響恶耽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜陕截,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一驳棱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧农曲,春花似錦社搅、人聲如沸驻债。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽合呐。三九已至,卻和暖如春笙以,著一層夾襖步出監(jiān)牢的瞬間淌实,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工拆祈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倘感,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓老玛,卻偏偏與公主長得像淤年,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子麸粮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

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