App卡頓-從零了解到系統(tǒng)解決

一、 卡頓有哪些場(chǎng)景

????首先檬果,回想下在什么情況下你會(huì)覺(jué)得某個(gè)App很卡,不妨設(shè)想現(xiàn)在從手機(jī)桌面打開(kāi)一個(gè)App-簡(jiǎn)書(shū)唐断。
????1 當(dāng)App啟動(dòng)后很久才進(jìn)入主頁(yè)面选脊,你會(huì)覺(jué)得卡;
????2 當(dāng)主頁(yè)面內(nèi)容很久才展示完全脸甘,你會(huì)覺(jué)得卡恳啥;
????3 當(dāng)在列表頁(yè)面滑動(dòng)時(shí)出現(xiàn)停頓,你會(huì)覺(jué)得卡丹诀;
????4 當(dāng)點(diǎn)擊某篇文章停留很久才跳轉(zhuǎn)钝的,你會(huì)覺(jué)得卡;
????5 當(dāng)點(diǎn)擊訂閱按鈕铆遭,很久才有訂閱成功反饋硝桩,你會(huì)覺(jué)得卡;

總結(jié)提煉下枚荣,你會(huì)發(fā)現(xiàn)卡頓這種視覺(jué)感知問(wèn)題歸根到底是事件處理和UI展示的綜合消耗時(shí)間超出了用戶(hù)感官系統(tǒng)的期待時(shí)間碗脊。精確一點(diǎn)就可給出如下定義:

二、卡頓定義

????在能夠感知的視覺(jué)場(chǎng)景中橄妆,當(dāng)事件處理(思考)和UI展示(表達(dá))的綜合消耗時(shí)間超過(guò)用戶(hù)視覺(jué)系統(tǒng)的最大期待時(shí)間衙伶,我們就說(shuō)出現(xiàn)了卡頓。
????在卡頓描述中有提到一個(gè)概念用戶(hù)視覺(jué)系統(tǒng)的期待時(shí)間害碾,這個(gè)期待時(shí)間是主觀的痕支,但要小于大多數(shù)用戶(hù)的期待時(shí)間,它在一定條件下又是客觀的蛮原。比如當(dāng)點(diǎn)擊訂閱按鈕卧须,App會(huì)彈出訂閱成功或者訂閱失敗彈框,有人等待1s也沒(méi)覺(jué)得有問(wèn)題,也有人超過(guò)0.4s就感覺(jué)體驗(yàn)很不爽花嘶,但我們開(kāi)發(fā)者要關(guān)注的是所有用戶(hù)的期待時(shí)間笋籽,所以閾值一定是讓大多數(shù)用戶(hù)感覺(jué)爽的,若點(diǎn)擊App中任意按鈕椭员、視圖车海,都在0.1s內(nèi)給出反饋,這樣基本上99%的人都是感覺(jué)-哇哦~你們App反應(yīng)好快隘击。
????除了上述事件反饋時(shí)間侍芝,還有一個(gè)我們?nèi)祟?lèi)視覺(jué)系統(tǒng)硬件帶來(lái)的期待時(shí)間,那就是連續(xù)動(dòng)畫(huà)中單個(gè)畫(huà)面的渲染時(shí)間埋同。連續(xù)的動(dòng)畫(huà)中一個(gè)畫(huà)面的如果在視覺(jué)暫留時(shí)間內(nèi)沒(méi)有渲染好州叠,顯示系統(tǒng)將會(huì)展示上一幀頁(yè)面,那么對(duì)于用戶(hù)來(lái)說(shuō)就是發(fā)生了卡頓凶赁。通常用fps衡量渲染速度咧栗,fps(frame per second)是一秒鐘系統(tǒng)的渲染頁(yè)面的總次數(shù)。渲染速度越快虱肄,平均一幀渲染時(shí)間就越短致板,我們就感覺(jué)越絲滑。但由于人類(lèi)的視覺(jué)暫留時(shí)間基本都大于16.6ms咏窿,所以我們單幀渲染時(shí)間小于16.6ms(也就是幀率60fps以上)就可以使大多數(shù)人感覺(jué)非常流暢斟或。

????通過(guò)卡頓的定義,我們找到了解決卡頓的關(guān)鍵兩要素:
????1 事件數(shù)據(jù)處理時(shí)間
????2 UI渲染時(shí)間
????我們要做的是在用戶(hù)能夠感知的使用場(chǎng)景中集嵌,給出優(yōu)化事件處理時(shí)間和UI渲染時(shí)間的方案缕粹。
????結(jié)合用戶(hù)感知最多的卡頓場(chǎng)景,可以得出一個(gè)較全面的卡頓解決方案:

三纸淮、最常見(jiàn)卡頓的解決方案

3.1 App冷啟動(dòng)優(yōu)化

冷啟動(dòng)具體時(shí)間段界定

startTime:用戶(hù)點(diǎn)擊桌面圖標(biāo)開(kāi)始
點(diǎn)擊桌面圖標(biāo)->點(diǎn)擊事件回調(diào)到桌面(Launcher) App->Launcher處理點(diǎn)擊事件,收集該圖標(biāo)相關(guān)的信息亚享,發(fā)起intent調(diào)用->跨進(jìn)程調(diào)用AMS啟動(dòng)對(duì)應(yīng)的進(jìn)程
然后再ActivityStarter打印log:

2021-12-16 14:18:50.402 24772-24772/com.example.demo V/JG: launcher onClick start
2021-12-16 14:18:50.403 534-945/system_process I/ActivityTaskManager: START u0 {flg=0x10000000 cmp=com.jingang.lifechange/.SplashActivity} from uid 10164
2021-12-16 14:18:50.449 534-563/system_process I/ActivityManager: Start proc 24932:com.jingang.lifechange/u0a162 for pre-top-activity {com.jingang.lifechange/com.jingang.lifechange.SplashActivity}
//第一句log是我們模擬桌面App的點(diǎn)擊事件咽块;第二句log是AMS開(kāi)始啟動(dòng)SplashActivity,第三句log是ams發(fā)現(xiàn)該Activity所在的進(jìn)程未啟動(dòng)去啟動(dòng)進(jìn)程欺税。

從點(diǎn)擊桌面到這兩個(gè)log打印侈沪,過(guò)程有很多步驟,但這些步驟里面沒(méi)有耗時(shí)操作晚凿,一般情況下非常短暫(2ms內(nèi))亭罪,而且沒(méi)有l(wèi)og,所以一般情況下把上述第二句logSTART u0 ~*的時(shí)間當(dāng)作App冷啟動(dòng)的開(kāi)始時(shí)間歼秽。當(dāng)然一些特殊情況需要定位問(wèn)題到底在哪邊需要精確定位時(shí)間应役,我們就要想辦法去無(wú)限接近用戶(hù)點(diǎn)擊桌面圖標(biāo)的時(shí)間,這個(gè)需要去了解Android 輸入系統(tǒng)或觀察Launcher app點(diǎn)擊日志(基本沒(méi)有),以后介紹箩祥。
但只有代碼運(yùn)行到自己的App進(jìn)程之后院崇,我們才能有所作為,所以還要記錄下冷啟動(dòng)時(shí)候App最早收到回調(diào)的時(shí)間點(diǎn)-這也是優(yōu)化的起點(diǎn)時(shí)間:

public class MainApplication extends Application {
    private static final String TAG = "lifeCycle:"+MainApplication.class.getName();
    @Override
    protected void attachBaseContext(Context base) {
        Log.v(TAG,"attachBaseContext");
        super.attachBaseContext(base);
    }
}

endTime:第一個(gè)頁(yè)面主體內(nèi)容展示出來(lái)結(jié)束
如果有splash頁(yè)面袍祖,那就是Home頁(yè)面主體展示出來(lái)結(jié)束底瓣。
home頁(yè)面主體展示出來(lái),比較精確的就是取第一幀圖像繪制出來(lái)的時(shí)間蕉陋。

    @Override
    protected void onResume() {
        super.onResume();
        Log.v(getTag(),"onResume");
        getWindow().getDecorView().getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
            @Override
            public void onDraw() {
                Log.v(getTag(),"onDecorView draw , draw time");
            }
        });
    }

當(dāng)然也可以利用系統(tǒng)log捐凭,如下的第二句log

2021-12-16 15:19:35.979 28022-28022/com.jingang.lifechange V/lifeCycle:MainActivity: onDecorView draw , draw time 0
2021-12-16 15:19:36.010 534-561/system_process I/ActivityTaskManager: Displayed com.jingang.lifechange/.MainActivity: +1s863ms
2021-12-16 15:19:36.018 28022-28022/com.jingang.lifechange V/lifeCycle:MainActivity: onDecorView draw , draw time 1
2021-12-16 15:19:36.040 28022-28022/com.jingang.lifechange V/lifeCycle:MainActivity: onDecorView draw , draw time 2
冷啟啟動(dòng)時(shí)間指標(biāo)

4s以?xún)?nèi)良,8s以外差————用戶(hù)點(diǎn)擊后桌面圖標(biāo)后凳鬓, 心里開(kāi)始 數(shù)1 茁肠、2、 3 到4頁(yè)面還沒(méi)有出來(lái)村视,用戶(hù)開(kāi)始著急官套,數(shù)到7、8沒(méi)出來(lái)用戶(hù)一般就放棄了蚁孔。也就是上面我們記錄的結(jié)束時(shí)間減去開(kāi)始時(shí)間最好不好超過(guò)4s奶赔。

冷啟動(dòng)優(yōu)化方案

原則: 視覺(jué)優(yōu)化、異步杠氢、 懶加載站刑、協(xié)調(diào)加載順序
實(shí)現(xiàn):
1)用戶(hù)點(diǎn)擊桌面應(yīng)用圖標(biāo)——到正式展示出來(lái)假如只有4S,但4S內(nèi)出現(xiàn)了點(diǎn)擊無(wú)反應(yīng)鼻百、黑屏绞旅、白屏,那用戶(hù)主觀感覺(jué)也是非常糟糕温艇。所以我們把視覺(jué)優(yōu)化放到第一個(gè)要優(yōu)化的項(xiàng)目因悲,最常見(jiàn)的就是把冷啟動(dòng)的Activity增加一個(gè)帶有背景(閃屏圖)的主體(Theme)。
2)把沒(méi)有必要放在UI線程中的初始化任務(wù)放入其他線程勺爱;
3)把沒(méi)有必要在應(yīng)用啟動(dòng)時(shí)的初始化任務(wù)移動(dòng)到真正使用之前晃琳,或者利用應(yīng)用線程空余時(shí)間進(jìn)行;
4)注意很多初始化任務(wù)是有順序的琐鲁,在優(yōu)化過(guò)程中這些順序要注意保持卫旱;
如果是一個(gè)大型項(xiàng)目,app啟動(dòng)初始化任務(wù)特別多围段,有很多初始化任務(wù)之間有加載順序問(wèn)題顾翼,初始化也不一定在UI線程進(jìn)行,那我們可以大干一場(chǎng)奈泪,構(gòu)建一個(gè)App啟動(dòng)器适贸。App啟動(dòng)器是一個(gè)任務(wù)調(diào)度工具類(lèi)灸芳,可以把不同的初始化任務(wù)按照順序在不同線程中執(zhí)行,從而使App啟動(dòng)正確而高效取逾,做好之后也可以在不同項(xiàng)目中復(fù)用耗绿。這個(gè)以后再探討如何設(shè)計(jì)和實(shí)現(xiàn)。

3.2 頁(yè)面跳轉(zhuǎn)卡頓優(yōu)化

頁(yè)面跳轉(zhuǎn)時(shí)間段界定
startTime:發(fā)起頁(yè)面用戶(hù)事件
endTime:打開(kāi)頁(yè)面首幀加載完成
頁(yè)面跳轉(zhuǎn)時(shí)間指標(biāo)
1s內(nèi)- 頁(yè)面秒開(kāi)砾隅,無(wú)他頁(yè)面秒開(kāi)基本稱(chēng)為一個(gè)用戶(hù)在App內(nèi)操作的一個(gè)潛在標(biāo)準(zhǔn)误阻,當(dāng)然跟用戶(hù)主觀感受有關(guān)。
頁(yè)面跳轉(zhuǎn)優(yōu)化概覽
普通模式下:Activity A跳轉(zhuǎn)Activity B生命周期

A onPause()->B onCreate()-> B onStart()->B onResume()->A onStop()

B頁(yè)面的首幀加載是在B onResume()回調(diào)后進(jìn)行View的測(cè)量晴埂、布局究反、繪制,同本文冷啟動(dòng)結(jié)束的時(shí)間節(jié)點(diǎn)儒洛,可以參考上面進(jìn)行精耐。
由頁(yè)面跳轉(zhuǎn)的計(jì)算開(kāi)始結(jié)束時(shí)間點(diǎn),可得如下具體點(diǎn)優(yōu)化點(diǎn):
1)頁(yè)面跳轉(zhuǎn)發(fā)起頁(yè)面Activity A琅锻,onPause()內(nèi)盡量減少UI線程耗時(shí)操作卦停,可提升這個(gè)頁(yè)面打開(kāi)其他頁(yè)面的速度;
2)頁(yè)面跳轉(zhuǎn)發(fā)起頁(yè)面Activity A恼蓬,onStop()的UI線程耗時(shí)操作惊完,雖然不會(huì)使頁(yè)面跳轉(zhuǎn)看起來(lái)加快,但因?yàn)閛nStop是這個(gè)用戶(hù)操作最后一個(gè)環(huán)節(jié)处硬,所以減少耗時(shí)操作可以減少出現(xiàn)ANR的概率小槐;
3)被打開(kāi)頁(yè)面Activity B 在onCreate()\onStart()\onResume()方法中盡量減少UI線程的耗時(shí)操作,提升這個(gè)頁(yè)面被打開(kāi)的速度 荷辕。比如一些耗時(shí)操作移動(dòng)到idleHandler中凿跳;
4)對(duì)Activity B 的View層級(jí)、布局疮方、繪制等進(jìn)行優(yōu)化也可以加快頁(yè)面B的打開(kāi)速度控嗜,這個(gè)會(huì)在接下來(lái)章節(jié)繼續(xù)展開(kāi)。
原則
根據(jù)不同模式下Activity啟動(dòng)骡显,涉及到的生命周期變化進(jìn)行跟蹤優(yōu)化疆栏。

3.3 頁(yè)面滑動(dòng),屬性動(dòng)畫(huà)蟆盐、幀動(dòng)畫(huà)等動(dòng)畫(huà)

動(dòng)畫(huà)的本質(zhì)是什么?
動(dòng)畫(huà)和視頻的本質(zhì)都是按一定順序快速展示的一組圖片遭殉,因?yàn)槿搜鄣囊曈X(jué)暫留原理就形成了連續(xù)移動(dòng)的感覺(jué)石挂。
圖片的本質(zhì)是什么?
一張圖片的本質(zhì)是一組像素點(diǎn)
圖片的這一組像素點(diǎn)如何得來(lái)
1 現(xiàn)成圖片:各種圖片格式险污,雖然可能有壓縮痹愚,但一張jpg富岳,png等格式的圖片本質(zhì)就是一組像素點(diǎn)。
????顯示的時(shí)候就是把這組像素點(diǎn)從網(wǎng)絡(luò)拯腮、硬盤(pán)等地方讀入到內(nèi)存窖式,由內(nèi)存完成一些校驗(yàn)工作,并緩存起來(lái)动壤,等待特定時(shí)機(jī)(接收到vsync信號(hào)時(shí))寫(xiě)入到顯示器緩存區(qū)-從而顯示出來(lái)萝喘。
2 由數(shù)據(jù)生成
????操作系統(tǒng)都提供一套用戶(hù)定義圖像api--比如Android的顯示系統(tǒng)中View就是提供給用戶(hù)自定義圖像的api,用戶(hù)按照一定規(guī)范調(diào)用api描述自己想要的圖像琼懊,系統(tǒng)在特定時(shí)機(jī)(接收到vsync信號(hào)時(shí))就把這種用戶(hù)規(guī)范的描述轉(zhuǎn)換成一組像素點(diǎn)阁簸,寫(xiě)入顯示器緩存,從而顯示出來(lái)哼丈。
????我們上面談到的頁(yè)面滑動(dòng)启妹、屬性動(dòng)畫(huà)都屬于第二種情況——圖片是由操作系統(tǒng)根據(jù)用戶(hù)的描述一步步生成,所以接下來(lái)的重點(diǎn)是討論這種情況如何顯示和優(yōu)化醉旦。
????計(jì)算機(jī)顯示一張圖片饶米,其實(shí)跟我們自己找人畫(huà)一張畫(huà)像然后送給朋友非常相似,都是由我們把想畫(huà)的場(chǎng)景告訴畫(huà)家车胡,畫(huà)家取紙張繪制檬输,最后我們拿到畫(huà)作,去展示給心愛(ài)的人吨拍。

顯示概覽

????在android系統(tǒng)上我們稍微深入一點(diǎn)褪猛,得到一個(gè)更詳細(xì)的流程。
Android顯示原理-從View到手機(jī)屏幕上的圖像

????從上述一張圖繪制流程圖可以看到羹饰,系統(tǒng)繪制一張圖比較耗時(shí)間的點(diǎn)在于1) 讀取和轉(zhuǎn)換用戶(hù)描述 ,2)繪制(包含渲染)
????除此之外伊滋,我們大多數(shù)繪制工作是要在ui線程進(jìn)行,雖然android系統(tǒng)有消息屏障機(jī)制可保證繪制任務(wù)優(yōu)先級(jí)很高队秩,但是ui線程并不能把當(dāng)前正在執(zhí)行的任務(wù)終止笑旺,所以在進(jìn)行繪制流程時(shí)候,遇到UI線程中有耗時(shí)很多的任務(wù)馍资,也會(huì)導(dǎo)致繪制被推遲筒主,從而造成卡頓、丟幀等鸟蟹。
????所以我們優(yōu)化從以下兩個(gè)方面進(jìn)行:
????1乌妙、布局優(yōu)化
????布局優(yōu)化就是指是采用盡量節(jié)約的方式指達(dá)到同樣的顯示效果。比如減少 View 層級(jí)建钥,這樣會(huì)加快 View 的循環(huán)遍歷過(guò)程藤韵,比如view層級(jí)優(yōu)化可以減少view;去除不必要的背景(背景是單獨(dú)繪制)熊经,可以使繪制內(nèi)容減少泽艘;減少View 的過(guò)度繪制欲险;提前把xml轉(zhuǎn)換成java代碼,減少解析時(shí)間等匹涮;
????2天试、 減少UI線程中耗時(shí)任務(wù)和異常阻塞
????前面有講到過(guò)UI線程會(huì)處理完當(dāng)前任務(wù),才進(jìn)行繪制然低,如果在我們申請(qǐng)繪制的時(shí)候有耗時(shí)任務(wù)在執(zhí)行喜每,那勢(shì)必會(huì)影響正常顯示,android系統(tǒng)三緩沖機(jī)制脚翘,所以原則上一個(gè)ui線程任務(wù)超過(guò)16*3=48ms的時(shí)候就會(huì)對(duì)繪制任務(wù)造成影響灼卢,所以我們要減少這些任務(wù)。在full GC的時(shí)候也停止ui線程来农,影響繪制造成卡頓鞋真。

如何檢測(cè)
1 布局優(yōu)化檢測(cè)
Hierarchy Viewer、開(kāi)發(fā)者模式過(guò)度繪制開(kāi)關(guān)等
2 ui耗時(shí)任務(wù)檢測(cè)
通過(guò)類(lèi)似下面的計(jì)算出ui線程每個(gè)任務(wù)執(zhí)行的時(shí)間沃于,找到耗時(shí)比較長(zhǎng)的時(shí)間進(jìn)行優(yōu)化涩咖。

getMainLooper().setMessageLogging(new LogPrinter(Log.INFO,"uiThread"));

可以通過(guò)hook等方法,插入定位問(wèn)題所需要的信息繁莹。

五 思考題目

系統(tǒng)有哪些監(jiān)控措施是處理卡頓的檩互?
答:ANR 、strictmode
本文分析的可全面咨演?
答:并沒(méi)有闸昨, 我們只是找了啟動(dòng)流程中最可能有問(wèn)題的地方拿出來(lái)分析講解,不代表其他地方?jīng)]有問(wèn)題薄风,比如跨進(jìn)程通信 饵较、AMS狀態(tài)、當(dāng)前系統(tǒng)cpu和內(nèi)存使用狀態(tài)等遭赂。
關(guān)于流暢度未來(lái)
1 卡頓預(yù)測(cè)
基于對(duì)用戶(hù)行為的洞察循诉,可以預(yù)測(cè)到接下來(lái)會(huì)該顯示哪些內(nèi)容,提前進(jìn)行數(shù)據(jù)初始化撇他,甚至提前走完所有繪制步驟茄猫。
2 分工與異步
對(duì)繪制過(guò)程再進(jìn)行重新解讀,將當(dāng)前順序執(zhí)行的再次進(jìn)行分工困肩,充分利用當(dāng)前多cpu和gpu架構(gòu)划纽。
3 顯示效果與功耗更加平衡
動(dòng)態(tài)多線程,動(dòng)態(tài)開(kāi)啟gpu
4 感官優(yōu)化
用戶(hù)覺(jué)得慢锌畸,這個(gè)問(wèn)題是“用戶(hù)覺(jué)得慢”勇劣,不一定是真的慢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蹋绽,一起剝皮案震驚了整個(gè)濱河市芭毙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卸耘,老刑警劉巖退敦,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蚣抗,居然都是意外死亡侈百,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)翰铡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钝域,“玉大人,你說(shuō)我怎么就攤上這事锭魔±ぃ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵迷捧,是天一觀的道長(zhǎng)织咧。 經(jīng)常有香客問(wèn)我,道長(zhǎng)漠秋,這世上最難降的妖魔是什么笙蒙? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮庆锦,結(jié)果婚禮上捅位,老公的妹妹穿的比我還像新娘。我一直安慰自己搂抒,他們只是感情好艇搀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著燕耿,像睡著了一般中符。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上誉帅,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天淀散,我揣著相機(jī)與錄音,去河邊找鬼蚜锨。 笑死档插,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亚再。 我是一名探鬼主播郭膛,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼氛悬!你這毒婦竟也來(lái)了则剃?” 一聲冷哼從身側(cè)響起耘柱,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棍现,沒(méi)想到半個(gè)月后调煎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡己肮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年士袄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谎僻。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娄柳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出艘绍,到底是詐尸還是另有隱情赤拒,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布诱鞠,位于F島的核電站需了,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏般甲。R本人自食惡果不足惜肋乍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望敷存。 院中可真熱鬧墓造,春花似錦、人聲如沸锚烦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)涮俄。三九已至蛉拙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彻亲,已是汗流浹背孕锄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留苞尝,地道東北人畸肆。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像宙址,于是被迫代替她去往敵國(guó)和親轴脐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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