Android內存優(yōu)化和開發(fā)過程中注意事項

Android開發(fā)過程當中澜建,軟件卡頓、軟件黑屏退出等等現(xiàn)象都跟內存相關钱烟,安卓軟件與ios軟件體驗同樣是流暢度差距很大租悄,所以我們在搭建架構和開發(fā)軟件過程當中一定要注意內存的管理和代碼的優(yōu)化

Android系統(tǒng)對軟件內存的分配機制

Android 為每個應用分配內存時,采用彈性的分配方式逻锐,即剛開始并不會給應用分配很多的內存夫晌,而是給每一個進程分配一個「夠用」的內存大小,這個大小值是根據(jù)每一個設備的實際的物理內存大小來決定的昧诱。隨著應用的運行和使用晓淀,Android 會為應用分配一些額外的內存大小。但是分配的大小是有限度的盏档,系統(tǒng)不可能為每一個應用分配無限大小的內存要糊。總之妆丘,Android 系統(tǒng)需要最大限度的讓更多的進程存活在內存中锄俄,以保證用戶再次打開應用時減少應用的啟動時間,提高用戶體驗勺拣。關于 Android 系統(tǒng)內存管理機制的相關細節(jié)奶赠,推薦大家閱讀下這兩篇文章:談談 Android 的內存管理機制、Android 操作系統(tǒng)的內存回收機制药有。

避免內存溢出

內存溢出(Out Of Memory 簡稱 OOM)毅戈,簡單地說內存溢出就是指程序運行過程中,申請的內存大于系統(tǒng)能夠提供的內存愤惰,導致無法申請到足夠的內存苇经,于是就發(fā)生了內存溢出。

減小對象的內存占用

避免 OOM 的第一步就是要盡量減少新分配出來的對象占用內存的大小宦言,盡量使用更加輕量的對象扇单。

使用更加輕量的數(shù)據(jù)結構

例如,我們可以考慮使用 ArrayMap/SparseArray 而不是 HashMap 等傳統(tǒng)數(shù)據(jù)結構奠旺。

通常的 HashMap 的實現(xiàn)方式更加消耗內存蜘澜,因為它需要一個額外的實例對象來記錄 Mapping 操作施流。另外,SparseArray 更加高效在于他們避免了對 key 與 value 的 autobox 自動裝箱鄙信,并且避免了裝箱后的解箱瞪醋。

正確的使用枚舉類型

枚舉類型(Enums),是 Java 語言中的一個特性装诡。但 Android 官方強烈建議不要在 Android 應用里面使用到 Enums银受,是因為枚舉類型在編譯之后會生成很多內部類,在移動設備上內存比較珍貴顯然會很占用內存鸦采。想了解枚舉的實現(xiàn)細節(jié)可以查看 Java 枚舉類型的實現(xiàn)原理 這篇文章蚓土。

所以了解了枚舉類型的實現(xiàn)原理可以發(fā)現(xiàn),在 Android 程序里不是不可以使用枚舉類型赖淤,而是推薦使用蜀漆。合理的使用枚舉類型可以做到一些很優(yōu)雅的操作,比如單例模式咱旱。

由反編譯后的代碼可知确丢,INSTANCE被聲明為static的,在類加載過程中吐限,虛擬機會保證一個類的<clinit>()方法在多線程環(huán)境中被正確的加鎖鲜侥、同步。所以诸典,枚舉實現(xiàn)是在實例化時是線程安全描函。

在序列化的時候 Java 僅僅是將枚舉對象的 name 屬性輸出到結果中,反序列化的時候則是通過java.lang.Enum的 valueOf 方法來根據(jù)名字查找枚舉對象狐粱。同時舀寓,編譯器是不允許任何對這種序列化機制的定制的,因此禁用了 writeObject肌蜻、readObject互墓、readObjectNoData、writeReplace 和 readResolve 等方法蒋搜。

普通的 Java 類的反序列化過程中篡撵,會通過反射調用類的默認構造函數(shù)來初始化對象。所以豆挽,即使單例中構造函數(shù)是私有的育谬,也會被反射給破壞掉。由于反序列化后的對象是重新 new 出來的帮哈,所以這就破壞了單例膛檀。

但是,枚舉的反序列化并不是通過反射實現(xiàn)的。所以宿刮,也就不會發(fā)生由于反序列化導致的單例破壞問題。

減小 Bitmap 對象的內存占用

Bitmap 是一個極容易消耗內存的大胖子私蕾,關于 Bitmap 內存占用大小詳情請參閱 Android 坑檔案:你的 Bitmap 究竟占多大內存僵缺?,所以減小創(chuàng)建出來的 Bitmap 的內存占用是很重要的踩叭,通常來說有下面 2 個措施:

縮放比例

在把圖片載入內存之前磕潮,我們需要先計算出一個合適的縮放比例,避免不必要的大圖載入容贝。

解碼格式

選擇 ALPHA_8/ARGB_4444/ARGB_8888/RBG_565自脯,存在很大差異。

模式描述占用字節(jié)

ALPHA_8Alpha 由 8 位組成1B

ARGB_44444 個 4 位組成 16 位斤富,每個色彩元素站 4 位2B

ARGB_88884 個 8 為組成 32 位膏潮,每個色彩元素站 8 位(默認)4B

RGB_565R 為 5 位,G 為 6 位满力,B 為 5 位共 16 位焕参,沒有Alpha2B

使用更小的圖片

在設計給到資源圖片的時候,我們需要特別留意這張圖片是否存在可以壓縮的空間油额,是否可以使用一張更小的圖片叠纷。

盡量使用更小的圖片不僅僅可以減少內存的使用,還可以避免出現(xiàn)大量的 InflationException潦嘶。假設有一張很大的圖片被 XML 文件直接引用涩嚣,很有可能在初始化視圖的時候就會因為內存不足而發(fā)生 InflationException,這個問題的根本原因其實是發(fā)生了 OOM掂僵。

JPG vs PNG vs WebP

不了解這三種圖片格式的建議看下 JPG 和 PNG 有什么區(qū)別航厚?、WebP 原理和 Android 支持現(xiàn)狀介紹 這兩篇文章锰蓬。

圖片壓縮

圖片壓縮相關知識推薦看下騰訊音樂技術團隊的Android 中圖片壓縮分析(上)阶淘、Android 中圖片壓縮分析(下)兩篇文章。

了解了圖片壓縮的相關知識互妓,我們可以自己寫算法來實現(xiàn)圖片壓縮溪窒,也可以使用優(yōu)秀的開源庫,比如:魯班冯勉。

內存對象的重復利用

除了減小對象對內存的占用澈蚌,合理的復用內存對象也是很好避免內存溢出的方式。

大多數(shù)對象的復用灼狰,最終實施的方案都是利用對象池技術宛瞄,要么是在編寫代碼的時候顯式的在程序里面去創(chuàng)建對象池,然后處理好復用的實現(xiàn)邏輯交胚,要么就是利用系統(tǒng)框架既有的某些復用特性達到減少對象的重復創(chuàng)建份汗,從而減少內存的分配與回收盈电。

LruCache

在 Android 中最常用的一個緩存算法是 LRU(Least Recently Use),就是當超出緩存容量的時候杯活,就優(yōu)先淘汰鏈表中最近最少使用的那個數(shù)據(jù)匆帚。

使用 LruCache 可以緩存 Bitmap 對象,相同LruCache 只是對內存中對象有效旁钧,如果我們想把圖片吸重、視頻等文件緩存在磁盤上可以使用 JakeWharton 大神開源的 DiskLruCache。

使用 Glide

Glide 是一個快速高效的 Android 圖片加載庫歪今,注重于平滑的滾動嚎幸。Glide 提供了易用的 API,高性能寄猩、可擴展的圖片解碼管道(decode pipeline)嫉晶,以及自動的資源池技術。

Glide 也是 Google 推薦過的開源項目田篇,詳見:Glide车遂。

復用系統(tǒng)自帶的資源

Android 系統(tǒng)本身內置了很多的資源(例如:字符串慌申、顏色颗胡、圖片、動畫箕昭、樣式以彬呻、簡單布局等等)衣陶,這些資源都可以在應用程序中直接引用。

這樣做不僅僅可以減少應用程序的自身負重闸氮,減小 APK 的大小剪况,另外還可以一定程度上減少內存的開銷,復用性更好蒲跨。但是也有必要留意 Android 系統(tǒng)的版本差異性译断,對那些不同系統(tǒng)版本上表現(xiàn)存在很大差異,不符合需求的情況或悲,還是需要應用程序自身內置進去孙咪。

復用 ConvertView

在 ListView、GridView 等出現(xiàn)大量重復子組件的視圖里面對 ConvertView 的復用巡语。

onLowMemory()

OnLowMemory 是 Android 提供的API翎蹈,在系統(tǒng)內存不足,所有后臺程序(優(yōu)先級為 Background 的進程男公,不是指后臺運行的進程)都被殺死時荤堪,系統(tǒng)會調用 OnLowMemory。

系統(tǒng)提供的回調有:Application、Activity澄阳、Fragementice拥知、Service、ContentProvider碎赢。

onTrimMemory()

OnTrimMemory 是 Android 4.0 之后提供的 API低剔,系統(tǒng)會根據(jù)不同的內存狀態(tài)來回調。

系統(tǒng)提供的回調有:Application揩抡、Activity户侥、Fragementice镀琉、Service峦嗤、ContentProvider。

OnTrimMemory的參數(shù)是一個 int 數(shù)值屋摔,代表不同的內存狀態(tài)烁设。

當 App 在前臺運行時,該函數(shù)的 level (從低到高)有:

TRIM_MEMORY_RUNNING_MODERATE

系統(tǒng)開始運行在低內存狀態(tài)下 App 正在運行钓试,不會被殺掉装黑。

TRIM_MEMORY_RUNNING_LOW

系統(tǒng)運行在更加低內存狀態(tài)下,App 在運行弓熏,不會被殺掉 App 可以清理一些資源來保證系統(tǒng)的流暢恋谭。

TRIM_MEMORY_RUNNING_CRITICAL

系統(tǒng)運行在相當?shù)蛢却鏍顟B(tài)下,App 在運行挽鞠,且系統(tǒng)不認為可以殺掉此 App疚颊,系統(tǒng)要開始殺掉后臺進程。此時信认,App 應該去釋放一些不重要的資源材义。

當 App 在后臺運行時,level 狀態(tài)有:

TRIM_MEMORY_UI_HIDDEN:

App 的 UI 不可見嫁赏,App 可以清理 UI 使用的較大的資源其掂。

當 App 進入后臺 LRU List 時:

TRIM_MEMORY_BACKGROUND

系統(tǒng)運行在低內存下,App 進程在 LRU List 開始處附近潦蝇,盡管 App 沒有被殺掉的風險款熬,但是系統(tǒng)也許已經正在殺后臺進程。App 應該清理一些容易恢復的資源攘乒。

TRIM_MEMORY_MODERATE

系統(tǒng)運行在低內存下华烟,App 進程在 LRU List 中間處附件,App 此時有被殺的可能持灰。

TRIM_MEMORY_COMPLETE

系統(tǒng)運行在低內存下盔夜,App 是首先被殺的選擇之一,App 應該及時清理掉恢復 App 到前臺狀態(tài),不重要的所有資源喂链。

另外返十,一個 App 占用內存越多,則系統(tǒng)清理后臺 LRU List 時椭微,越可能優(yōu)先被清理洞坑。所以,內存使用我們要謹慎使用蝇率。

避免在 onDraw 方法里面執(zhí)行對象的創(chuàng)建

類似 onDraw 等頻繁調用的方法迟杂,一定需要注意避免在這里做創(chuàng)建對象的操作,因為他會迅速增加內存的使用本慕,而且很容易引起頻繁的 GC排拷,甚至是內存抖動。

序列化

?Android 中實現(xiàn)序列化一般用 Serializable 和 Parcelable 兩種方式锅尘。

兩者最大的區(qū)別在于 存儲媒介的不同监氢,Serializable 使用 I/O 讀寫存儲在硬盤上,而 Parcelable 是直接 在內存中讀寫藤违。很明顯浪腐,內存的讀寫速度通常大于 IO 讀寫,所以在 Android 中傳遞數(shù)據(jù)優(yōu)先選擇 Parcelable顿乒。Serializable 會使用反射议街,序列化和反序列化過程需要大量 I/O 操作, Parcelable 自已實現(xiàn)封送和解封(marshalled &unmarshalled)操作不需要用反射璧榄,數(shù)據(jù)也存放在 Native 內存中特漩,效率要快很多。

Parcelable 的性能比 Serializable 好犹菱,在內存開銷方面較小拾稳,所以在內存間數(shù)據(jù)傳輸時推薦使用 Parcelable(如 Activity 間傳輸數(shù)據(jù))。

而 Serializable 可將數(shù)據(jù)持久化方便保存腊脱,所以在需要保存或網(wǎng)絡傳輸數(shù)據(jù)時選擇 Serializable访得,因為 Android 不同版本 Parcelable 可能不同,所以不推薦使用 Parcelable進行數(shù)據(jù)持久化.

StringBuilder

在有些時候陕凹,代碼中會需要使用到大量的字符串拼接的操作悍抑,這種時候有必要考慮使用 StringBuilder 來替代頻繁的+。

避免內存泄漏

內存泄漏(Memory Leak)指程序運行過程中分配內存給臨時變量杜耙,用完之后卻沒有被 GC 回收搜骡,始終占用著內存,既不能被使用也不能分配給其他程序佑女,于是就發(fā)生了內存泄漏记靡。

內存泄露有時不嚴重且不易察覺谈竿,這樣開發(fā)者就不知道存在內存泄露,但有時也會很嚴重摸吠,甚至會提示你 OOM空凸。

Context 的泄露

在 Android 開發(fā)中,最容易引發(fā)的內存泄漏問題的是 Context寸痢。比如 Activity 的 Context呀洲,就包含大量的內存引用,一旦泄漏了 Context啼止,也意味泄漏它指向的所有對象道逗。

造成 Activity 泄漏的常見原因:

靜態(tài)引用 Activity

在類中定義了靜態(tài) Activity 變量,把當前運行的 Activity 實例賦值于這個靜態(tài)變量献烦。如果這個靜態(tài)變量在 Activity 生命周期結束后沒有清空滓窍,就導致內存泄漏。

因為 static 變量是貫穿這個應用的生命周期的仿荆,所以被泄漏的 Activity 就會一直存在于應用的進程中贰您,不會被垃圾回收器回收坏平。

單例中保存 Activity

在單例模式中拢操,如果 Activity 經常被用到,那么在內存中保存一個 Activity 實例是很實用的舶替。

但是由于單例的生命周期是應用程序的生命周期令境,這樣會強制延長 Activity 的生命周期,這是相當危險而且不必要的顾瞪,無論如何都不能在單例子中保存類似 Activity 的對象舔庶。

在調用 Singleton 的 getInstance() 方法時傳入了 Activity。那么當 instance 沒有釋放時陈醒,這個 Activity 會一直存在惕橙,因此造成內存泄露。

考慮使用 Application Context 而不是 Activity Context

對于大部分非必須使用 Activity Context 的情況(Dialog 的 Context 就必須是 Activity Context)钉跷,我們都可以考慮使用 Application Context 而不是 Activity 的 Context弥鹦,這樣可以避免不經意的 Activity 泄露。

Inner Classes

內部類的優(yōu)勢可以提高可讀性和封裝性爷辙,而且可以訪問外部類彬坏,不幸的是,導致內存泄漏的原因膝晾,就是內部類持有外部類實例的強引用(例如在內部類中持有 Activity 對象)栓始。

解決方法:

將內部類變成靜態(tài)內部類;

如果有強引用 Activity 中的屬性血当,則將該屬性的引用方式改為弱引用幻赚;

在業(yè)務允許的情況下禀忆,當 Activity 執(zhí)行 onDestory 時,結束這些耗時任務落恼。

避免使用異步回調

異步回調被執(zhí)行的時間不確定油湖,很有可能發(fā)生在 Activity 已經被銷毀之后,這不僅僅很容易引起 crash领跛,還很容易發(fā)生內存泄露乏德。

注意臨時 Bitmap 對象的及時回收

雖然在大多數(shù)情況下,我們會對 Bitmap 增加緩存機制吠昭,但是在某些時候喊括,部分 Bitmap 是需要及時回收的。

例如:臨時創(chuàng)建的某個相對比較大的 Bitmap 對象矢棚,在經過變換得到新的 Bitmap 對象之后郑什,應該盡快回收原始的 Bitmap,這樣能夠更快釋放原始 Bitmap 所占用的空間蒲肋。

需要特別留意的是 Bitmap 類里面提供的 createBitmap() 方法蘑拯,這個函數(shù)返回的 Bitmap 有可能和 source bitmap 是同一個,在回收的時候兜粘,需要特別檢查 source bitmap 與 return bitmap 的引用是否相同申窘,只有在不等的情況下,才能夠執(zhí)行 source bitmap 的 recycle 方法孔轴。

監(jiān)聽器的注銷

在 Android 程序里面存在很多需要 register 與 unregister 的監(jiān)聽器剃法,我們需要確保在合適的時候及時 unregister 那些監(jiān)聽器。自己手動 add 的 listener路鹰,需要記得及時 remove 這個 listener贷洲。

?Cursor 對象是否及時關閉

在程序中我們經常會進行查詢數(shù)據(jù)庫的操作,但時常會存在不小心使用 Cursor 之后沒有及時關閉的情況晋柱。這些 Cursor 的泄露优构,反復多次出現(xiàn)的話會對內存管理產生很大的負面影響,我們需要謹記對 Cursor 對象的及時關閉雁竞。

緩存容器中的對象泄漏

有時候钦椭,我們?yōu)榱颂岣邔ο蟮膹陀眯园涯承ο蠓诺骄彺嫒萜髦校墒侨绻@些對象沒有及時從容器中清除浓领,也是有可能導致內存泄漏的玉凯。

例如:針對 2.3 的系統(tǒng),如果把 drawable 添加到緩存容器联贩,因為 drawable 與 View 的強應用漫仆,很容易導致 activity 發(fā)生泄漏。而從 4.0 開始泪幌,就不存在這個問題盲厌。解決這個問題署照,需要對 2.3 系統(tǒng)上的緩存 drawable 做特殊封裝,處理引用解綁的問題吗浩,避免泄漏的情況建芙。

?WebView 的泄漏

Android 中的 WebView 存在很大的兼容性問題,不僅僅是 Android 系統(tǒng)版本的不同對 WebView 產生很大的差異懂扼,另外不同的廠商出貨的 ROM 里面 WebView 也存在著很大的差異禁荸。更嚴重的是標準的 WebView 存在內存泄露的問題,看這里 WebView causes memory leak - leaks the parent Activity阀湿。

所以通常根治這個問題的辦法是為 WebView 開啟另外一個進程赶熟,通過 AIDL 與主進程進行通信, WebView 所在的進程可以根據(jù)業(yè)務的需要選擇合適的時機進行銷毀陷嘴,從而達到內存的完整釋放映砖。

Lint Tool

Lint 是Android Studio 提供的代碼掃描分析工具,它可以幫助我們發(fā)現(xiàn)代碼結構/質量問題灾挨,同時提供一些解決方案邑退,而且這個過程不需要我們手寫測試用例。

Lint 發(fā)現(xiàn)的每個問題都有描述信息和等級(和測試發(fā)現(xiàn) bug 很相似)劳澄,我們可以很方便地定位問題地技,同時按照嚴重程度進行解決。

點擊Analyze > Inspect Code可打開 Lint 工具浴骂。

詳細使用介紹可查看 Android 開發(fā)文檔 - 使用 Lint 改進您的代碼乓土、Android 性能優(yōu)化:使用 Lint 優(yōu)化代碼宪潮、去除多余資源 這兩篇文章溯警,使用比較簡單,網(wǎng)上介紹資源很多狡相,這里不再詳細介紹梯轻。

adb dumpsys

dumpsys 是 Android 系統(tǒng)提供的一個工具,可以查看系統(tǒng)服務的相關信息尽棕,dumpsys 通過 adb 命令來調用喳挑。

查看指定進程包名的內存使用情況:

$ adb shell dumpsys meminfo <包名>

輸出內容如下:

當然 dumpsys 的功能還有很多,可以查看 Android? 開發(fā)文檔 - dumpsys滔悉、dumpsys 命令用法 這兩篇文章了解更多用法伊诵。

Heap Viewer

Heap Viewer 是 DDMS 中的一個工具,實時查看 App 分配的內存大小和空閑內存大小回官,可幫助查找內存泄露曹宴。Heap Viewer 支持 5.0 及以上的系統(tǒng),現(xiàn)在已經棄用歉提,官方推薦使用 Memory Profiler 來查看 App 內存分配情況笛坦。

Memory Profiler

Memory Profiler 是 Android Profiler 中的一個組件区转,可幫助開發(fā)者識別導致應用卡頓、OOM 和內存泄露版扩。它顯示一個應用內存使用量的實時圖表废离,可以捕獲堆轉儲、強制執(zhí)行垃圾回收以及跟蹤內存分配礁芦。

可以在View > Tool Windows > Android Profiler中打開 Memory Profiler 界面蜻韭。

Memory Profile 的具體使用可查看 Android 開發(fā)文檔 - 使用 Memory Profiler 查看 Java 堆和內存分配、Android Studio 3.0 利用 Android Profiler 測量應用性能 這兩篇文章柿扣。

MAT

MAT(Memory Analyzer Tool)湘捎,一個基于 Eclipse 的內存分析工具,是一個快速窄刘、功能豐富的 Java Heap 分析工具窥妇,它可以幫助我們查找內存泄漏和減少內存消耗。

使用內存分析工具從眾多的對象中進行分析娩践,快速的計算出在內存中對象的占用大小活翩,看看是誰阻止了垃圾收集器的回收工作,并可以通過報表直觀的查看到可能造成這種結果的對象翻伺。

當然 MAT 也有獨立的不依賴 Eclipse 的版本材泄,只不過這個版本在調試 Android 內存的時候,需要將 Android Studio 生成的文件進行轉換吨岭,才可以在獨立版本的 MAT 上打開拉宗。.

一般情況下使用 Memory Profiler 就可以檢測出內存泄露的大致位置,使用 MAT 可以更詳細的分析內存的具體情況辣辫。

MAT 下載 點擊這里旦事,使用教程可查看 Eclipse Wiki - MemoryAnalyzer,也可以參考 Android 內存優(yōu)化之一:MAT 使用入門急灭、Android內存優(yōu)化之二:MAT使用進階 這兩篇文章姐浮。

LeakCanary

LeakCanary 是一個用于檢測 Android 內存泄漏的開源庫,上面介紹的 Memory Profiler葬馋、MAT 使用起來比較復雜卖鲤,LeakCanary 堪稱傻瓜式的內存泄露檢測工具。

使用方式詳見https://square.github.io/leakcanary畴嘶,也可參考 LeakCanary 中文使用說明 這篇文章蛋逾。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市窗悯,隨后出現(xiàn)的幾起案子区匣,更是在濱河造成了極大的恐慌,老刑警劉巖蟀瞧,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沉颂,死亡現(xiàn)場離奇詭異条摸,居然都是意外死亡,警方通過查閱死者的電腦和手機铸屉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門钉蒲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人彻坛,你說我怎么就攤上這事顷啼。” “怎么了昌屉?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵钙蒙,是天一觀的道長。 經常有香客問我间驮,道長躬厌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任竞帽,我火速辦了婚禮扛施,結果婚禮上,老公的妹妹穿的比我還像新娘屹篓。我一直安慰自己疙渣,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布堆巧。 她就那樣靜靜地躺著妄荔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谍肤。 梳的紋絲不亂的頭發(fā)上啦租,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音谣沸,去河邊找鬼刷钢。 笑死,一個胖子當著我的面吹牛乳附,可吹牛的內容都是我干的。 我是一名探鬼主播伴澄,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼赋除,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了非凌?” 一聲冷哼從身側響起举农,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敞嗡,沒想到半個月后颁糟,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體航背,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年棱貌,在試婚紗的時候發(fā)現(xiàn)自己被綠了玖媚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡婚脱,死狀恐怖今魔,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情障贸,我是刑警寧澤错森,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站篮洁,受9級特大地震影響涩维,放射性物質發(fā)生泄漏。R本人自食惡果不足惜袁波,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一激挪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锋叨,春花似錦垄分、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至偷卧,卻和暖如春豺瘤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背听诸。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工坐求, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晌梨。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓桥嗤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親仔蝌。 傳聞我的和親對象是個殘疾皇子泛领,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內容