Android性能優(yōu)化(十)之App瘦身攻略

1、 前言

如果你對(duì)App優(yōu)化比較敏感,那么Apk安裝包的大小就一定不會(huì)忽視。關(guān)于瘦身的原因,大概有以下幾個(gè)方面:

  • 對(duì)于用戶來說,在功能差別不大的前提下,更小的Apk大小意味更少的流量消耗,也意味著更多的用戶下載;
  • 對(duì)于產(chǎn)品來說,大于競(jìng)品的Apk意味著較低的下載基數(shù),不利于驗(yàn)證產(chǎn)品策略;
  • 對(duì)于開發(fā)人員來說,App瘦身則是一次技術(shù)優(yōu)化、技術(shù)提升的機(jī)會(huì);

2、 Apk的組成

2.1 Apk典型組成

一個(gè)典型的Apk組成

下表為Apk目錄及文件說明:

文件/目錄 說明
assets/ 存放一些靜態(tài)文件,可以通過AssertManager訪問
lib/ 如果該目錄存在,一般存放的是NDK編譯出來的so
META-INF/ 保存著APK的簽名信息
res/ 資源文件所在目錄,包含drawable、layout等
AndroidManifest.xml 程序全局配置文件
classes.dex Java Class,被DEX編譯后可供Dalvik/ART虛擬機(jī)所理解的文件格式
resources.arsc 編譯后生成的二進(jìn)制資源文件

2.2 示例分析

做App瘦身之前需要對(duì)自己App現(xiàn)有組成有一個(gè)清晰的認(rèn)識(shí),上述解壓的方式只能粗略的看出具體目錄的大小,但是有用信息仍然有限。

2.2.1 Android Studio Analyze APK

Android Studio 2.2之后有一個(gè)功能Analyze APK,方便簡單,功能還是Google自帶的靠譜;

  • 查看apk中任意文件的大小,得到一個(gè)直觀的認(rèn)識(shí);
  • 了解Dex文件的組成,查看使用那些開源庫等;
  • 查看二進(jìn)制文件(如AndroidMainfest.xml等);
  • Apk的比較,便于發(fā)現(xiàn)兩個(gè)版本之間的區(qū)別。
Analyze APK的使用
2.2.2 反編譯工具ClassyShark

ClassShark 是一款查看Android執(zhí)行文件(apk)的瀏覽工具,可以很方便的打開APK/Class/Jar/res等文件和分析里面的內(nèi)容。

ClassyShark的使用
2.2.3 Nimbledroid

NimbleDroid 是美國哥倫比亞大學(xué)的博士創(chuàng)業(yè)團(tuán)隊(duì)研發(fā)出來的分析Android app性能指標(biāo)的系統(tǒng),分析的方式有靜態(tài)和動(dòng)態(tài)兩種方式,其中靜態(tài)分析可以分析出APK安裝包中大文件排行榜,各種知名SDK的大小以及占代碼整體的比例,各種類型文件的大小以及占排行,各種知名SDK的方法數(shù)以及占所有dex中方法數(shù)的比例。

文件大小排行

方法數(shù)統(tǒng)計(jì)

總結(jié):這三種方式都可以對(duì)Apk的組成有一個(gè)更加清晰的認(rèn)識(shí),但更加推薦使用AndroidStudio自帶的Analyze APK,簡單、高效。

使用Analyze APK查看到文件大小之后發(fā)現(xiàn),classes.dex、res、assets、lib等文件較大,哪里的脂肪多,我們就去抽哪里。確定優(yōu)化方向:

  1. 代碼部分:冗余代碼、無用功能、代碼混淆、方法數(shù)縮減等;
  2. 資源部分:冗余資源、資源混淆、圖片處理等;
  3. 對(duì)So文件的處理等。

3、 Apk瘦身之代碼瘦身

3.1 移除無用代碼、功能

隨著版本的迭代,部分功能可能已被去掉,但是其代碼還存在項(xiàng)目中。移除無用代碼以及無用功能,有助于減少代碼量,直接體現(xiàn)就是Dex的體積會(huì)變小。

備注:根據(jù)經(jīng)驗(yàn),不用的代碼在項(xiàng)目中存在屬于一個(gè)普遍現(xiàn)象,相當(dāng)于僵尸代碼,而且這類代碼過多也會(huì)導(dǎo)致Dex文件過大。

3.2 移除無用的庫、避免功能雷同的庫

3.2.1 項(xiàng)目中基礎(chǔ)功能的庫要統(tǒng)一實(shí)現(xiàn),避免出現(xiàn)多套網(wǎng)絡(luò)請(qǐng)求、圖片加載器等實(shí)現(xiàn)。
3.2.2 不用的庫要及時(shí)移除出項(xiàng)目,例如我們之前確定要由某推送切換到某推送的時(shí)候,此時(shí)就要把最初項(xiàng)目中的推送庫去掉,而不應(yīng)該只是注釋掉其注冊(cè)代碼。
3.2.3 一些功能可以曲線救國的話就不要引入SDK,例如定位功能,可以不引入定位SDK,而通過拿到經(jīng)緯度然后調(diào)用相關(guān)接口來實(shí)現(xiàn);同樣實(shí)現(xiàn)了功能而沒有引入SDK。
3.2.4 而引入SDK也需要考慮其方法數(shù),可以使用ClassyShark、Nimbledroid或者APK method count等工具查看。

備注:根據(jù)經(jīng)驗(yàn),項(xiàng)目中存在之前使用之后不使用的庫的情況并不罕見。

3.3 啟用Proguard

代碼混淆也稱為花指令,是將計(jì)算機(jī)程序的代碼轉(zhuǎn)換為功能上等價(jià)但是難以閱讀、理解的行為。Proguard是一個(gè)免費(fèi)的Java類文件壓縮、優(yōu)化、混淆、預(yù)先驗(yàn)證的工具,可以檢測(cè)和移除未使用的類、字段、方法、屬性,優(yōu)化字節(jié)碼并移除未使用的指令,并將代碼中的類、字段、方法的名字改為簡短、無意義的名字。

可以看出Proguard不僅能將diamante中的各種元素改的簡短,還可以移除冗余代碼,因此可以減少Dex文件的大小。

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile(‘proguard-android.txt'),
                    'proguard-rules.pro'
        }
    }
    ...
}

其中,proguard-android.txt是獲取默認(rèn)ProGuard設(shè)置,proguard-rules.pro文件用于添加自定義ProGuard規(guī)則。

備注:對(duì)于Proguard,雖然效果很明顯,但仍然需要謹(jǐn)慎;

  • 代碼混淆會(huì)拖慢項(xiàng)目構(gòu)建速度,因此debug模式下關(guān)掉Proguard不至于RD在運(yùn)行代碼的時(shí)候抓狂;
  • 因?yàn)樵赿ebug模式下關(guān)掉了Proguard,如果混淆規(guī)則沒有配置好,在Release模式可能會(huì)出現(xiàn)debug模式下不出現(xiàn)的Bug;
  • Proguard也不是你想搞就能搞,如果App做了一段時(shí)間之后再來做Proguard,項(xiàng)目包結(jié)構(gòu)不規(guī)范的話,那Proguard的規(guī)則將會(huì)非常多。而短時(shí)間內(nèi)調(diào)整包結(jié)構(gòu)也是一件相當(dāng)痛苦的事情。

3.4 縮減方法數(shù)

一般情況下縮減方法數(shù),都是為了Android著名的64k方法數(shù)問題,此處不再回顧,參見之前《關(guān)于Multidex的系列文章》。而這里說縮減方法數(shù)的目的,是為了App瘦身。

通過《Dalvik Executable format》,我們可以看到Dex文件的組成。而從header-item表中的method-ids-size字段可以看出,方法數(shù)縮減之后,可以減少方法列表的大小;同時(shí),方法在Dex文件中的占用空間也減少了,App自然被瘦身。

而縮減方法數(shù),除了上面寫到的普遍方法:移除無用方法、庫、使用較小的SDK之外還有:

  1. 避免在內(nèi)部類中訪問外部類的私有方法、變量。當(dāng)在Java內(nèi)部類(包含匿名內(nèi)部類)中訪問外部類的私有方法、變量的時(shí)候,編譯器會(huì)生成額外的方法,會(huì)增加方法數(shù);
  2. 避免調(diào)用派生類中的未被覆寫的方法,避免在派生類中調(diào)用未覆寫的基類的方法;避免用派生類的對(duì)象調(diào)用派生類中未覆蓋的基類的方法。調(diào)用派生類中的未被覆蓋的方法時(shí),會(huì)多產(chǎn)生一個(gè)方法數(shù);
  3. 去掉部分類的get、set方法;當(dāng)然這樣會(huì)犧牲一些面向?qū)ο蟮挠^念。

4、 Apk瘦身之資源瘦身

對(duì)于重要性,代碼和資源的瘦身同樣重要,但是從效果上來說,資源文件的瘦身效果比代碼的瘦身效果要好非常多。很有可能費(fèi)力許久在代碼上得到的瘦身效果,在資源文件瘦身中輕松就得到了。

4.1 移除無用的資源文件

移除無用資源文件要比移除無用代碼容易,在Android Studio的任何文件中右擊,選擇清除無用資源即可刪除沒有用到的資源文件。

Remove Unused Resources

備注:在build.gradle中設(shè)置shrinkResources為true后,每次打包的時(shí)候就會(huì)自動(dòng)排除無用的資源。shrinkResources需要配合minifyEnabled一起使用。但是根據(jù)我的實(shí)驗(yàn):無用的資源還是會(huì)被打進(jìn)Apk中,只是變成一張黑圖,體積也非常小,只有不到100b。有使用錯(cuò)誤的地方歡迎指正!

4.2 Drawable目錄只保留一份資源

這條開發(fā)者中討論的比較多,確實(shí)Google強(qiáng)烈建議根據(jù)不同屏幕密度準(zhǔn)備多套切圖資源來做適配的。但是鑒于Android上對(duì)UI要求不會(huì)是最頂級(jí)的那種高度,以及即便是放在合適(注意這兩個(gè)字)一個(gè)的目錄下,在不同的分辨率下也會(huì)做自動(dòng)的適配(等比例拉伸、縮放);因此還是建議:對(duì)UI不是最頂級(jí)要求的話根據(jù)自己的用戶群體機(jī)型放在一個(gè)合適的目錄下。這樣毋庸置疑可以縮減Res的大小,進(jìn)而減少Apk的體積。

備注:圖片放在不恰當(dāng)?shù)哪夸浻锌赡軙?huì)對(duì)內(nèi)存產(chǎn)生較大的影響,可以參考之前的文章《Android 性能優(yōu)化(五)之細(xì)說 Bitmap》

4.3 對(duì)圖片進(jìn)行壓縮

之前我在項(xiàng)目里發(fā)現(xiàn)過文件大小過1M的圖片,可能是由于UI同學(xué)和RD同學(xué)的雙重疏忽,導(dǎo)致如此大的圖片到了項(xiàng)目中,對(duì)Apk體積的影響自然不言而喻。

可以考慮使用TinyPng、pngquant、ImageOptim等工具對(duì)圖片進(jìn)行壓縮,這些工具可以減少PNG文件大小,同時(shí)保持圖像質(zhì)量。

此處以TinyPng為例:TinyPng是一個(gè)相當(dāng)不錯(cuò)的圖片壓縮工具,在保持alpha通道的情況下對(duì)PNG的壓縮可以達(dá)到1/3之內(nèi),而且用肉眼基本上分辨不出壓縮的損失。這張3.4M的圖片被壓縮到了984.7k,壓縮率高達(dá)71%。

使用TinyPng壓縮圖片示例

也有同學(xué)開發(fā)了一個(gè)AndroidStudio插件:TinyPngPlugin,能夠批量地壓縮項(xiàng)目中的圖片,更加方便。

備注:需要注意的是在Android構(gòu)建流程中AAPT會(huì)使用內(nèi)置的壓縮算法來優(yōu)化res/drawable/目錄下的PNG圖片,但也可能會(huì)導(dǎo)致本來已經(jīng)優(yōu)化過的圖片體積變大,可以通過在build.gradle中設(shè)置cruncherEnabled來禁止AAPT采用默認(rèn)方式優(yōu)化我們已經(jīng)優(yōu)化過的圖片。

aaptOptions {
    cruncherEnabled = false
}

4.4 PNG轉(zhuǎn)換JPG

PNG是一種無損格式,JPG是有損格式。JPG在處理顏色很多的圖片時(shí),根據(jù)壓縮率的不同,有時(shí)會(huì)去掉一些肉眼識(shí)別差距較小的中間顏色。但是PNG對(duì)于無損這個(gè)基本要求,會(huì)嚴(yán)格保留所有的色彩數(shù)。所以圖片尺寸大,或者色彩數(shù)量多特別是漸變色的多的時(shí)候,PNG的體積會(huì)明顯大于JPG。

在這種情況下,我們可以有所取舍。小尺寸、色彩較少或者有alpha通道透明度的時(shí)候,使用PNG;大尺寸、色彩漸變多的使用JPG。

備注:根據(jù)經(jīng)驗(yàn),對(duì)于可以直接使用JPG格式的圖片,最好不要從PNG轉(zhuǎn)換為JPG,而是出圖的時(shí)候直接出JPG格式的圖片,相對(duì)而言,后者的效果更好。

4.5 使用矢量圖

可縮放矢量圖形(英語:Scalable Vector Graphics,SVG)是一種基于可擴(kuò)展標(biāo)記語言(XML),用于描述二維矢量圖形的圖形格式。SVG由W3C制定,是一個(gè)開放標(biāo)準(zhǔn)。可以使用矢量圖形來創(chuàng)建獨(dú)立于分辨率的圖標(biāo)和其他可伸縮圖片。使用矢量圖片能夠有效的減少App中圖片所占用的大小,矢量圖形在Android中表示為VectorDrawable對(duì)象。

優(yōu)點(diǎn)

  • 圖片擴(kuò)展性:不損傷圖片質(zhì)量,一套圖適配所有;
  • 圖片非常小:比使用位圖小十幾倍,有利于減小apk體積;

缺點(diǎn)

  • 性能優(yōu)損失,系統(tǒng)渲染VectorDrawable需要花費(fèi)更多時(shí)間,因?yàn)槭噶繄D的初始化加載會(huì)比相應(yīng)的光柵圖片消耗更多的CPU周期,但是兩者之間的內(nèi)存消耗和性能接近;
  • 矢量圖主要用在色調(diào)單一的icon。

4.6 使用WebP

Google于2010年提出了一種新的圖片壓縮格式 — WebP,為圖片提供了無損和有損壓縮能力,同時(shí)在有損條件下支持透明通道。據(jù)官方實(shí)驗(yàn)顯示:無損WebP相比PNG減少26%大小;有損WebP在相同的SSIM(Structural Similarity Index,結(jié)構(gòu)相似性)下相比JPEG減少25%~34%的大小;有損WebP也支持透明通道,大小通常約為對(duì)應(yīng)PNG的1/3。同時(shí),谷歌于2014年提出了動(dòng)態(tài)WebP,拓展WebP使其支持動(dòng)圖能力。動(dòng)態(tài)WebP相比GIF支持更豐富的色彩,并且也占用更小空間,更適應(yīng)移動(dòng)網(wǎng)絡(luò)的動(dòng)圖播放。

優(yōu)點(diǎn):

  • WebP在同畫質(zhì)下體積更小,WebP支持透明度,壓縮比比JPEG更高但顯示效果卻不輸于JPEG;
  • 可以通過工具、云服務(wù)等進(jìn)行PNG到WebP的轉(zhuǎn)換;

缺點(diǎn):

  • Android從4.0才開始WebP的原生支持,意味著要兼容4.0以下機(jī)型需要添加適配庫;當(dāng)然現(xiàn)在市面上適配4.0以下的應(yīng)用已經(jīng)很少了。
  • Android 4.2.1+才支持顯示含透明度的WebP,因此最低版本小于4.2.1的App也不是想用就能用的。可以將不顯示透明度的圖片轉(zhuǎn)換為WebP。

4.7 資源混淆

在Apk打包過程中,aapt會(huì)將每一個(gè)資源生成一個(gè)對(duì)應(yīng)的int數(shù)值,而我們通過這個(gè)int值來查找使用資源。在Apk構(gòu)成中,我們可以看到里面有一個(gè)resources.arsc文件,里面保存著資源id和資源key的映射關(guān)系。

當(dāng)調(diào)用圖片時(shí),先找到drawable分類,再根據(jù)當(dāng)前的系統(tǒng)config找到匹配的config表,根據(jù)id找到對(duì)應(yīng)的res數(shù)據(jù)。drawable在arsc中是當(dāng)做string類型保存的,res數(shù)據(jù)中有這個(gè)資源在res string pool池中的索引。根據(jù)這個(gè)索引可以在字符串池中找到一個(gè)字符串。這個(gè)字符串其實(shí)就是一個(gè)路徑,比如:res/drawable-xhdpi/icon.png;混淆就是將這個(gè)路徑改為R/s/f.png;同時(shí)修改resources.arsc文件的映射關(guān)系。這樣就能清楚的看出來資源混淆能減小Apk的原因:

  • resources.arsc變小;
  • 文件信息變小,采用了超短路徑,res/drawable-xhdpi/icon.png被修改為R/s/f.png。

這里推薦微信的資源混淆方案:AndResGuard

4.8 資源在線化

將部分使用頻率不高的資源例如圖片,放在網(wǎng)上,在恰當(dāng)?shù)臅r(shí)機(jī)提前下載,這樣也能節(jié)約部分空間。

5、 Apk瘦身之So瘦身

So(shared object,共享庫)是機(jī)器可以直接運(yùn)行的二進(jìn)制代碼,是Android上的動(dòng)態(tài)鏈接庫,類似于Windows上的dll。每一個(gè)Android應(yīng)用所支持的ABI是由其APK提供的.so文件決定的,這些so文件被打包在apk文件的lib/目錄下。

So的常見的場(chǎng)景如:加解密算法、音視頻編解碼、核心代碼等。在生成SO文件時(shí),需要考慮適配市面上不同手機(jī)CPU架構(gòu),而生成支持不同平臺(tái)的SO文件進(jìn)行兼容。目前Android共支持七種不同類型的CPU架構(gòu),分別是:ARMv5,ARMv7 (從2010年起),x86 (從2011年起),Mips (從2012年起),ARMv8,Mips64和x86_64 (從2014年起)。

理論上對(duì)應(yīng)CPU架構(gòu)的So的執(zhí)行效率是最高的,但是這樣會(huì)導(dǎo)致在libs目錄下放置各個(gè)架構(gòu)平臺(tái)的So文件,Apk文件的大小自然也就更大了。那么我們自然想到縮減Libs的目錄,一般情況(注意限定)下留下armeabi目錄即可,armeabi目錄下的So可以兼容別的平臺(tái)的So,但是性能會(huì)有所損耗,失去對(duì)特定平臺(tái)的優(yōu)化。

因此需要根據(jù)自己使用到的So功能來做具體的區(qū)分:對(duì)于性能敏感模塊使用的So可以都放在armeabi目錄,然后通過代碼判斷設(shè)備的CPU類型,再加載其對(duì)應(yīng)架構(gòu)的SO文件,例如微信就是這么做的。既縮減了Apk的體積,也不影響性能敏感模塊的執(zhí)行。

微信So的使用

移除特定平臺(tái)So的方式,這樣打包就只保存armeabi里的So。

ndk {
    //設(shè)置支持的SO庫架構(gòu)
    abiFilters  'armeabi'
}

備注:原本x86架構(gòu)的CPU是不支持運(yùn)行arm架構(gòu)的So,但I(xiàn)ntel和Google合作在x86機(jī)子的系統(tǒng)內(nèi)核層之上加入了一個(gè)名為houdini的Binary Translator(二進(jìn)制轉(zhuǎn)換中間層),這個(gè)中間層會(huì)在運(yùn)行期間動(dòng)態(tài)的讀取arm指令并將之轉(zhuǎn)換為x86指令去執(zhí)行。

6、 Apk瘦身之7Zip壓縮

我們知道Apk文件實(shí)際上就是一個(gè)Zip文件。Android SDK的打包工具apkbuilder采用的是Deflate算法將Android App的代碼、資源等文件進(jìn)行壓縮,壓縮成Zip格式,然后簽名發(fā)布。

既然是壓縮,那能不能改進(jìn)其壓縮方式,獲取更小的Apk文件?通過分析Apk打包的流程圖我們可以發(fā)現(xiàn)SignedJarBuilder類對(duì)整個(gè)工程包括代碼Dex和一些課壓縮的資源、文件進(jìn)行壓縮,使用的是JDK中zip包下提供的算法。

使用7Zip壓縮

簡單的方式我們可以在不改變App編譯器工作的情況下,對(duì)生成的Apk文件進(jìn)行二次壓縮,同樣使用Deflate算法,但是將壓縮等級(jí)從標(biāo)準(zhǔn)提升到極限壓縮。提高壓縮級(jí)別可在不對(duì)Apk包本身的內(nèi)容做任何修改的情況下得到更小的Apk。

備注:

  • 需要注意這樣極限壓縮之后的簽名被破壞,需要重新簽名。
  • Android平臺(tái)對(duì)Apk安裝包的解壓算法只支持Deflate算法,其它算法如LZMA,雖然壓縮率更好,但是由于Android平臺(tái)默認(rèn)不支持,所以如果采用這種算法壓縮Apk,會(huì)導(dǎo)致Apk無法安裝。
  • 目前在Mac上沒發(fā)現(xiàn)好用的7Zip壓縮軟件,需要在Windows下使用。

7、 App瘦身總結(jié):

7.1 代碼瘦身

  • 移除無用代碼、功能;
  • 移除無用的庫、避免功能雷同的庫;
  • 啟用Proguard;
  • 縮減方法數(shù);

7.2 資源瘦身

  • 移除無用的資源文件;
  • Drawable目錄只保留一份資源;
  • 對(duì)圖片進(jìn)行壓縮;
  • PNG轉(zhuǎn)換JPG;
  • 使用矢量圖;
  • 使用WebP;
  • 資源混淆;
  • 資源在線化;

7.3 So瘦身

  • 在允許的情況下,針對(duì)用戶機(jī)型分布保留特定架構(gòu)的So;

7.4 7Zip壓縮

使用7Zip對(duì)Apk進(jìn)行極限壓縮。

7.5 其它

  • 類如插件化,將Dex與資源文件放在服務(wù)端,需要時(shí)下載;但是插件化實(shí)施以及與現(xiàn)有項(xiàng)目結(jié)合難度不小,也超出本文主題,不細(xì)說;
  • 通過在 build.gradle配置include來針對(duì)每個(gè)CPU架構(gòu)生成單獨(dú)的安裝包,按照架構(gòu)上傳Apk;但是這個(gè)方案在國內(nèi)應(yīng)用市場(chǎng)幾乎沒有采用的,只能在Google Play上使用。
  • 一點(diǎn)經(jīng)驗(yàn):對(duì)Apk進(jìn)行瘦身,瘦身So以及資源文件是見效最快的操作。瘦身So以及刪除不用的圖片、壓縮圖片之后,Apk會(huì)縮減很大的比例;而針對(duì)Dex的優(yōu)化可能作用不會(huì)很明顯。

參考:

歡迎關(guān)注微信公眾號(hào):定期分享Java、Android干貨!

歡迎關(guān)注
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,826評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,227評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,447評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,807評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,001評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評(píng)論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,243評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評(píng)論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,709評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,996評(píng)論 2 374

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