iOS 卡頓優(yōu)化

卡頓原因分析:

1.屏幕顯示圖像的原理:

  • CPU:負(fù)責(zé)對(duì)象的創(chuàng)建和銷毀、對(duì)象屬性的調(diào)整、布局計(jì)算到千、文本的計(jì)算和排版、圖片的格式轉(zhuǎn)換和解碼赴穗、圖像的繪制(Core Graphics)

  • GPU: 負(fù)責(zé)紋理的渲染(將數(shù)據(jù)渲染到屏幕))

  • CPU 和 GPU 的協(xié)作:


    由上圖可知憔四,要在屏幕上顯示視圖,需要CPU和GPU一起協(xié)作般眉,CPU計(jì)算好顯示的內(nèi)容提交到GPU了赵,GPU渲染完成后將結(jié)果放到幀緩存區(qū),隨后視頻控制器會(huì)按照 VSync 信號(hào)逐行讀取幀緩沖區(qū)的數(shù)據(jù)甸赃,經(jīng)過可能的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示柿汛。

  • 垂直同步技術(shù): 讓CPU和GPU在收到vSync信號(hào)后再開始準(zhǔn)備數(shù)據(jù),防止撕裂感和跳幀埠对,通俗來講就是保證每秒輸出的幀數(shù)不高于屏幕顯示的幀數(shù)络断。

  • 雙緩沖技術(shù): iOS是雙緩沖機(jī)制,前幀緩存和后幀緩存,CPU計(jì)算完GPU渲染后放入緩沖區(qū)中,當(dāng)GPU下一幀已經(jīng)渲染完放入緩沖區(qū)项玛,且視頻控制器已經(jīng)讀完前幀貌笨,GPU會(huì)等待vSync(垂直同步信號(hào))信號(hào)發(fā)出后,瞬間切換前后幀緩存,并讓CPU開始準(zhǔn)備下一幀數(shù)據(jù)
    安卓4.0后采用三重緩沖襟沮,多了一個(gè)后幀緩沖锥惋,可降低連續(xù)丟幀的可能性,但會(huì)占用更多的CPU和GPU

  • 屏幕顯示圖像的原理: 圖像的顯示可以簡(jiǎn)單理解成先經(jīng)過CPU的計(jì)算/排版/編解碼等操作臣嚣,然后交由GPU去完成渲染放入緩沖中净刮,當(dāng)視頻控制器接受到vSync時(shí)會(huì)從緩沖中讀取已經(jīng)渲染完成的幀并顯示到屏幕上。

iOS手機(jī)默認(rèn)刷新率是60hz硅则,所以GPU渲染只要達(dá)到60fps就不會(huì)產(chǎn)生卡頓淹父。
以60fps為例,vSync會(huì)每16.67ms發(fā)出怎虫,如在16.67ms內(nèi)沒有準(zhǔn)備好下一幀數(shù)據(jù)就會(huì)使畫面停留在上一幀暑认,產(chǎn)生卡頓困介,例如圖中第3幀渲染完成之前一直顯示的是第2幀的內(nèi)容。

2.圖片加載流程

  • 假設(shè)我們使用 +imageWithContentsOfFile: 方法從磁盤中加載一張圖片蘸际,這個(gè)時(shí)候的圖片并沒有解壓縮座哩;
  • 然后將生成的 UIImage 賦值給 UIImageView
  • 接著一個(gè)隱式的 CATransaction 捕獲到了 UIImageView 圖層樹的變化
  • 在主線程的下一個(gè) runloop 到來時(shí),Core Animation 提交了這個(gè)隱式的 transaction 粮彤,這個(gè)過程可能會(huì)對(duì)圖片進(jìn)行 copy 操作根穷,而受圖片是否字節(jié)對(duì)齊等因素的影響,這個(gè) copy 操作可能會(huì)涉及以下部分或全部步驟:
    (1).分配內(nèi)存緩沖區(qū)用于管理文件 IO 和解壓縮操作
    (2). 將文件數(shù)據(jù)從磁盤讀到內(nèi)存中导坟;
    (3).將壓縮的圖片數(shù)據(jù)解碼成未壓縮的位圖形式屿良,這是一個(gè)非常耗時(shí)的 CPU 操作漆魔;
    (4). 最后 Core Animation 中CALayer使用未壓縮的位圖數(shù)據(jù)渲染 UIImageView 的圖層然评。
    (5). CPU計(jì)算好圖片的Frame,對(duì)圖片解壓之后.就會(huì)交給GPU來做圖片渲染
  • 渲染流程:
    (1).GPU獲取獲取圖片的坐標(biāo)
    (2).將坐標(biāo)交給頂點(diǎn)著色器(頂點(diǎn)計(jì)算)
    (3).將圖片光柵化(獲取圖片對(duì)應(yīng)屏幕上的像素點(diǎn))
    (4). 片元著色器計(jì)算(計(jì)算每個(gè)像素點(diǎn)的最終顯示的顏色值)
    (5).從幀緩存區(qū)中渲染到屏幕上
為什么要解壓縮圖片:

既然圖片的解壓縮需要消耗大量的 CPU 時(shí)間,那么我們?yōu)槭裁催€要對(duì)圖片進(jìn)行解壓縮呢笙瑟?是否可以不經(jīng)過解壓縮递递,而直接將圖片顯示到屏幕上呢喷橙?答案是否定的。要想弄明白這個(gè)問題登舞,我們首先需要知道什么是位圖
其實(shí)贰逾,位圖就是一個(gè)像素?cái)?shù)組,數(shù)組中的每個(gè)像素就代表著圖片中的一個(gè)點(diǎn)逊躁。我們?cè)趹?yīng)用中經(jīng)常用到的 JPEG 和 PNG 圖片就是位圖似踱。
不管是 JPEG 還是 PNG 圖片,都是一種壓縮的位圖圖形格式稽煤。只不過 PNG 圖片是無損壓縮核芽,并且支持 alpha 通道,而 JPEG 圖片則是有損壓縮酵熙,可以指定 0-100% 的壓縮比轧简。
所以在將磁盤中的圖片渲染到屏幕之前,必須先要得到圖片的原始像素?cái)?shù)據(jù)匾二,才能執(zhí)行后續(xù)的繪制操作哮独,這就是為什么需要對(duì)圖片解壓縮的原因。

3. 卡頓原因:

上面講解了圖片顯示的原理和屏幕渲染的原理察藐,造成卡頓的原因有很多皮璧,最主要的原因是因?yàn)榘l(fā)生了掉幀。
由上面屏幕顯示的原理分飞,采用了垂直同步機(jī)制的手機(jī)設(shè)備悴务。在 VSync 信號(hào)到來后,系統(tǒng)圖形服務(wù)會(huì)通過 CADisplayLink 等機(jī)制通知 App,App 主線程開始在 CPU 中計(jì)算顯示內(nèi)容讯檐,比如視圖的創(chuàng)建羡疗、布局計(jì)算、圖片解碼别洪、文本繪制等叨恨。隨后 CPU 會(huì)將計(jì)算好的內(nèi)容提交到 GPU 去,由 GPU 進(jìn)行變換挖垛、合成痒钝、渲染。隨后 GPU 會(huì)把渲染結(jié)果提交到幀緩沖區(qū)去晕换,等待下一次 VSync 信號(hào)到來時(shí)顯示到屏幕上午乓。由于垂直同步的機(jī)制,如果在一個(gè) VSync 時(shí)間內(nèi)闸准,CPU 或者 GPU 沒有完成內(nèi)容提交,則那一幀就會(huì)被丟棄梢灭,等待下一次機(jī)會(huì)再顯示夷家,而這時(shí)顯示屏?xí)A糁暗膬?nèi)容不變。這就是界面卡頓的原因敏释。
在開發(fā)中库快,CPU和GPU中任何一個(gè)壓力過大,都會(huì)導(dǎo)致掉幀現(xiàn)象钥顽,所以在開發(fā)時(shí)义屏,也需要分別對(duì)CPU和GPU壓力進(jìn)行評(píng)估和優(yōu)化。


卡頓監(jiān)控:

  • 主線程卡頓監(jiān)控蜂大。通過子線程監(jiān)測(cè)主線程的runLoop闽铐,判斷兩個(gè)狀態(tài)區(qū)域之間的耗時(shí)是否達(dá)到一定閾值。
  • FPS監(jiān)控奶浦。要保持流暢的UI交互兄墅,App 刷新率應(yīng)該當(dāng)努力保持在 60fps。FPS的監(jiān)控實(shí)現(xiàn)原理澳叉,上面已經(jīng)探討過這里略過隙咸。

1.RunLoop監(jiān)測(cè)卡頓

loop的狀態(tài)

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {

    kCFRunLoopEntry , // 進(jìn)入 loop

    kCFRunLoopBeforeTimers , // 觸發(fā) Timer 回調(diào)

    kCFRunLoopBeforeSources , // 觸發(fā) Source0 回調(diào)

    kCFRunLoopBeforeWaiting , // 等待 mach_port 消息

    kCFRunLoopAfterWaiting ), // 接收 mach_port 消息

    kCFRunLoopExit , // 退出 loop

    kCFRunLoopAllActivities  // loop 所有狀態(tài)改變

}

NSRunLoop調(diào)用方法主要就是在kCFRunLoopBeforeSources和kCFRunLoopBeforeWaiting之間,還有kCFRunLoopAfterWaiting之后,也就是如果我們發(fā)現(xiàn)這兩個(gè)時(shí)間內(nèi)耗時(shí)太長(zhǎng),那么就可以判定出此時(shí)主線程卡頓。

實(shí)現(xiàn)思路:只需要另外再開啟一個(gè)線程,實(shí)時(shí)計(jì)算這兩個(gè)狀態(tài)區(qū)域之間的耗時(shí)是否到達(dá)某個(gè)閥值,便能揪出這些性能殺手成洗。

閥值設(shè)定:假定連續(xù)5次超時(shí)50ms認(rèn)為卡頓(當(dāng)然也包含了單次超時(shí)250ms)

2.FPS && CADisplayLink

CADisplayLink是CoreAnimation提供的另一個(gè)類似于NSTimer的類五督,它總是在屏幕完成一次更新之前啟動(dòng),它的接口設(shè)計(jì)的和NSTimer很類似瓶殃,所以它實(shí)際上就是一個(gè)內(nèi)置實(shí)現(xiàn)的替代充包,但是和timeInterval以秒為單位不同,CADisplayLink有一個(gè)整型的frameInterval屬性碌燕,指定了間隔多少幀之后才執(zhí)行误证。默認(rèn)值是1继薛,意味著每次屏幕更新之前都會(huì)執(zhí)行一次。但是如果動(dòng)畫的代碼執(zhí)行起來超過了六十分之一秒愈捅,你可以指定frameInterval為2遏考,就是說動(dòng)畫每隔一幀執(zhí)行一次(一秒鐘30幀)。使用CADisplayLink監(jiān)控界面的FPS值.

卡頓優(yōu)化:

1.CPU優(yōu)化:

  • 盡量用輕量級(jí)的對(duì)象蓝谨,比如用不到事件處理的地方使用CALayer取代UIView

  • 盡量提前計(jì)算好布局(例如cell行高)

  • 不要頻繁地調(diào)用和調(diào)整UIView的相關(guān)屬性灌具,比如frame、bounds譬巫、transform等屬性咖楣,盡量減少不必要的調(diào)用和修改(UIView的顯示屬性實(shí)際都是CALayer的映射,而CALayer本身是沒有這些屬性的芦昔,都是初次調(diào)用屬性時(shí)通過resolveInstanceMethod添加并創(chuàng)建Dictionary保存的诱贿,耗費(fèi)資源)

  • Autolayout會(huì)比直接設(shè)置frame消耗更多的CPU資源,當(dāng)視圖數(shù)量增長(zhǎng)時(shí)會(huì)呈指數(shù)級(jí)增長(zhǎng).

  • 圖片的size最好剛好跟UIImageView的size保持一致咕缎,減少圖片顯示時(shí)的處理計(jì)算

  • 控制一下線程的最大并發(fā)數(shù)量

  • 盡量把耗時(shí)的操作放到子線程

  • 文本處理(尺寸計(jì)算珠十、繪制、CoreText和YYText):
    (1). 計(jì)算文本寬高boundingRectWithSize:options:context: 和文本繪制drawWithRect:options:context:放在子線程操作
    (2). 使用CoreText自定義文本空間凭豪,在對(duì)象創(chuàng)建過程中可以緩存寬高等信息焙蹭,避免像UILabel/UITextView需要多次計(jì)算(調(diào)整和繪制都要計(jì)算一次),且CoreText直接使用了CoreGraphics占用內(nèi)存小嫂伞,效率高孔厉。(YYText)

  • 圖片處理(解碼、繪制)
    圖片都需要先解碼成bitmap才能渲染到UI上帖努,iOS創(chuàng)建UIImage撰豺,不會(huì)立刻進(jìn)行解碼,只有等到顯示前才會(huì)在主線程進(jìn)行解碼然磷,固可以使用Core Graphics中的CGBitmapContextCreate相關(guān)操作提前在子線程中進(jìn)行強(qiáng)制解壓縮獲得位圖.

  • TableViewCell 復(fù)用: 在cellForRowAtIndexPath:回調(diào)的時(shí)候只創(chuàng)建實(shí)例郑趁,快速返回cell,不綁定數(shù)據(jù)姿搜。在willDisplayCell: forRowAtIndexPath:的時(shí)候綁定數(shù)據(jù)(賦值)

  • 高度緩存: 在tableView滑動(dòng)時(shí)寡润,會(huì)不斷調(diào)用heightForRowAtIndexPath:,當(dāng) cell 高度需要自適應(yīng)時(shí)舅柜,每次回調(diào)都要計(jì)算高度梭纹,會(huì)導(dǎo)致 UI 卡頓。為了避免重復(fù)無意義的計(jì)算致份,需要緩存高度变抽。

  • 視圖層級(jí)優(yōu)化: 不要?jiǎng)討B(tài)創(chuàng)建視圖,在內(nèi)存可控的前提下,緩存subview。善用hidden绍载。

  • 減少視圖層級(jí): 減少subviews個(gè)數(shù)诡宗,用layer繪制元素. 少用 clearColor,maskToBounds击儡,陰影效果等塔沃。

  • 減少多余的繪制操作.

  • 圖片優(yōu)化:
    (1)不要用JPEG的圖片,應(yīng)當(dāng)使用PNG圖片阳谍。
    (2)子線程預(yù)解碼(Decode)蛀柴,主線程直接渲染。因?yàn)楫?dāng)image沒有Decode矫夯,直接賦值給imageView會(huì)進(jìn)行一個(gè)Decode操作鸽疾。
    (3)優(yōu)化圖片大小,盡量不要?jiǎng)討B(tài)縮放(contentMode)训貌。
    (4)盡可能將多張圖片合成為一張進(jìn)行顯示制肮。

  • 減少透明 view: 使用透明view會(huì)引起blending,在iOS的圖形處理中递沪,blending主要指的是混合像素顏色的計(jì)算弄企。最直觀的例子就是,我們把兩個(gè)圖層疊加在一起区拳,如果第一個(gè)圖層的透明的,則最終像素的顏色計(jì)算需要將第二個(gè)圖層也考慮進(jìn)來意乓。這一過程即為Blending樱调。

  • 理性使用-drawRect:
    當(dāng)你使用UIImageView在加載一個(gè)視圖的時(shí)候,這個(gè)視圖雖然依然有CALayer届良,但是卻沒有申請(qǐng)到一個(gè)后備的存儲(chǔ)笆凌,取而代之的是使用一個(gè)使用屏幕外渲染,將CGImageRef作為內(nèi)容士葫,并用渲染服務(wù)將圖片數(shù)據(jù)繪制到幀的緩沖區(qū)乞而,就是顯示到屏幕上,當(dāng)我們滾動(dòng)視圖的時(shí)候慢显,這個(gè)視圖將會(huì)重新加載爪模,浪費(fèi)性能。所以對(duì)于使用-drawRect:方法荚藻,更傾向于使用CALayer來繪制圖層屋灌。因?yàn)槭褂肅ALayer的-drawInContext:,Core Animation將會(huì)為這個(gè)圖層申請(qǐng)一個(gè)后備存儲(chǔ)应狱,用來保存那些方法繪制進(jìn)來的位圖共郭。那些方法內(nèi)的代碼將會(huì)運(yùn)行在 CPU上,結(jié)果將會(huì)被上傳到GPU。這樣做的性能更為好些除嘹。
    靜態(tài)界面建議使用-drawRect:的方式写半,動(dòng)態(tài)頁面不建議。

  • 按需加載:
    局部刷新尉咕,刷新一個(gè)cell就能解決的叠蝇,堅(jiān)決不刷新整個(gè) section 或者整個(gè)tableView,刷新最小單元元素龙考。
    利用runloop提高滑動(dòng)流暢性蟆肆,在滑動(dòng)停止的時(shí)候再加載內(nèi)容,像那種一閃而過的(快速滑動(dòng))晦款,就沒有必要加載炎功,可以使用默認(rèn)的占位符填充內(nèi)容。

  • RunLoop優(yōu)化tableview加載多圖:如果要從網(wǎng)絡(luò)加載高清大圖到UITableViewCell上缓溅,而且每個(gè)Cell上面加載多張圖片蛇损,當(dāng)cell數(shù)量過多的時(shí)候,我們需要保持流暢度和加載速度坛怪。

1,因?yàn)檫@里用到了Runloop循環(huán),那么我們可以監(jiān)聽到runloop的每次循環(huán)淤齐,
在每一次循環(huán)當(dāng)中我們考慮去進(jìn)行一次圖片下載和布局。
2,既然要在每次循環(huán)執(zhí)行一次任務(wù)袜匿,
我們可以先把所有圖片加載的任務(wù)代碼塊添加到一個(gè)數(shù)組當(dāng)中更啄,
每次循環(huán)取出第一個(gè)任務(wù)進(jìn)行執(zhí)行。*
3,因?yàn)閞unloop在閑置的時(shí)候會(huì)自動(dòng)休眠居灯,
所以我們要想辦法讓runloop始終處于循環(huán)中的狀態(tài)祭务。

2.GPU 優(yōu)化

  • 盡量避免短時(shí)間內(nèi)大量圖片的顯示,盡可能將多張圖片合成一張進(jìn)行顯示

  • GPU能處理的最大紋理尺寸是4096x4096怪嫌,一旦超過這個(gè)尺寸义锥,就會(huì)占用CPU資源進(jìn)行處理,所以紋理盡量不要超過這個(gè)尺寸

  • GPU會(huì)將多個(gè)視圖混合在一起再去顯示岩灭,混合的過程會(huì)消耗CPU資源拌倍,盡量減少視圖數(shù)量和層次

  • 減少透明的視圖(alpha<1),不透明的就設(shè)置opaqueYES噪径,GPU就不會(huì)去進(jìn)行alpha的通道合成

  • 盡量避免出現(xiàn)離屏渲染.

  • 合理使用光柵化 shouldRasterize: 光柵化是把GPU的操作轉(zhuǎn)到CPU上柱恤,生成位圖緩存,直接讀取復(fù)用熄云。 CALayer會(huì)被光柵化為bitmap膨更,shadowscornerRadius等效果會(huì)被緩存缴允。 更新已經(jīng)光柵化的layer荚守,會(huì)造成離屏渲染珍德。 bitmap超過100ms沒有使用就會(huì)移除。 受系統(tǒng)限制矗漾,緩存的大小為 2.5X Screen Size锈候。 shouldRasterize 適合靜態(tài)頁面顯示,動(dòng)態(tài)頁面會(huì)增加開銷敞贡。如果設(shè)置了shouldRasterize為 YES泵琳,那也要記住設(shè)置rasterizationScalecontentsScale

  • 異步渲染.在子線程繪制誊役,主線程渲染获列。例如 VVeboTableViewDemo

  • 什么是離屏渲染?
    在OpenGL中蛔垢,GPU有2種渲染方式
    On-Screen Rendering:當(dāng)前屏幕渲染击孩,在當(dāng)前用于顯示的屏幕緩沖區(qū)進(jìn)行渲染操作
    Off-Screen Rendering:離屏渲染,在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作
    離屏渲染消耗性能的原因
    需要?jiǎng)?chuàng)建新的緩沖區(qū)
    離屏渲染的整個(gè)過程鹏漆,需要多次切換上下文環(huán)境巩梢,先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen);等到離屏渲染結(jié)束以后艺玲,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上括蝠,又需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕

  • 什么操作會(huì)導(dǎo)致離屏渲染?
    1.光柵化饭聚,layer.shouldRasterize = YES
    2.遮罩忌警,layer.mask
    3.圓角,同時(shí)設(shè)置layer.masksToBounds = YES秒梳、layer.cornerRadius大于0. 考慮通過CoreGraphics繪制裁剪圓角慨蓝,或者叫美工提供圓角圖片
    4.陰影,layer.shadowXXX端幼,如果設(shè)置了layer.shadowPath就不會(huì)產(chǎn)生離屏渲染.
    5.layer.allowsGroupOpacity為YES,layer.opacity的值小于1.0

參考:IOS面試考察(九):性能優(yōu)化相關(guān)問題

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弧满,一起剝皮案震驚了整個(gè)濱河市婆跑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庭呜,老刑警劉巖滑进,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異募谎,居然都是意外死亡扶关,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門数冬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來节槐,“玉大人搀庶,你說我怎么就攤上這事⊥欤” “怎么了哥倔?”我有些...
    開封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)揍庄。 經(jīng)常有香客問我咆蒿,道長(zhǎng),這世上最難降的妖魔是什么蚂子? 我笑而不...
    開封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任沃测,我火速辦了婚禮,結(jié)果婚禮上食茎,老公的妹妹穿的比我還像新娘蒂破。我一直安慰自己,他們只是感情好董瞻,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開白布寞蚌。 她就那樣靜靜地躺著,像睡著了一般钠糊。 火紅的嫁衣襯著肌膚如雪挟秤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天抄伍,我揣著相機(jī)與錄音艘刚,去河邊找鬼。 笑死截珍,一個(gè)胖子當(dāng)著我的面吹牛攀甚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岗喉,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼秋度,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了钱床?” 一聲冷哼從身側(cè)響起荚斯,我...
    開封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎查牌,沒想到半個(gè)月后事期,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纸颜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年兽泣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胁孙。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唠倦,死狀恐怖称鳞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情牵敷,我是刑警寧澤胡岔,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站枷餐,受9級(jí)特大地震影響靶瘸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜毛肋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一怨咪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧润匙,春花似錦诗眨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至厂财,卻和暖如春芋簿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背璃饱。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工与斤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荚恶。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓撩穿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親谒撼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子食寡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

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