內(nèi)存泄露和內(nèi)存優(yōu)化

內(nèi)存泄露和內(nèi)存優(yōu)化

對于Android來說,每一個APP的內(nèi)存是有限的碉克。你過你的內(nèi)存出現(xiàn)問題:泄露凌唬,長期占用過高,就會導致app易于被殺掉漏麦。頻繁的gc導致app卡頓等現(xiàn)象客税。

常見情況

  • Activity的Context的使用

    • 界面的Context靜態(tài)化
    • 單例式將界面的Context作為初始化入?yún)?shù),并且在單例模式保存
    • 特殊的唁奢,在Android 6.0中霎挟,不能使用Activity的Context通過接口getSystemService()來獲取各種Manager,如下所示:
    AActivityManager activityManager =(ActivityManager)MainActivity.this.getSystemService(Context.ACTIVITY_SERVICE);  
    

如上所示麻掸,在Android 6.0 中就會造成內(nèi)存泄露

  • 非靜態(tài)內(nèi)部類持有外部類的引用

在Java中酥夭,非靜態(tài)內(nèi)部類(包括匿名內(nèi)部類)都會持有外部類(一般是指Activity等頁面)的引用,當兩者的生命周期出現(xiàn)不一致的時候,很容易導致內(nèi)存泄露熬北。
  如下所示疙描,非常常見的幾種情況:
Hanlder

private Handler mHandler = new Handler() {
 @Override    
 public void handleMessage(Message msg)      
 {   
  super.handleMessage(msg);  
 }  
}; 

這里的Handler會引用Activity的引用,當handler調(diào)用postDelay的時候讶隐,若Activity已經(jīng)finish掉了起胰,因為這個 handler 會在一段時間內(nèi)繼續(xù)被 main Looper 持有,導致引用仍然存在巫延,在這段時間內(nèi)效五,如果內(nèi)存吃緊至超出,是很危險的炉峰。

Thread

public class ThreadActivity extends Activity {  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        new MyThread().start();  
    }  
  
    private class MyThread extends Thread {  
        @Override  
        public void run() {  
            super.run();  
            dosomthing();  
        }  
    }  
    private void dosomthing(){  
      
    }  
}  

假設(shè)MyThread的run函數(shù)是一個很費時的操作畏妖,當我們開啟該線程后,將設(shè)備的橫屏變?yōu)榱素Q屏疼阔,一般情況下當屏幕轉(zhuǎn)換時會重新創(chuàng)建Activity戒劫,按照我們的想法,老的Activity應該會被銷毀才對婆廊,然而事實上并非如此迅细。由于我們的線程是Activity的內(nèi)部類,所以MyThread中保存了Activity的一個引用淘邻,當MyThread的run函數(shù)沒有結(jié)束時茵典,MyThread是不會被銷毀的,因此它所引用的老的Activity也不會被銷毀列荔,因此就出現(xiàn)了內(nèi)存泄露的問題敬尺。

Runnable

  public class MainActivity extends Activity {
    ...
    Runnable ref1 = new MyRunable();
    Runnable ref2 = new Runnable() {
        @Override
        public void run() {

        }
    };
       ...
    }

ref1和ref2的區(qū)別是枚尼,ref2使用了匿名內(nèi)部類贴浙,也就是說當前的Activity會被ref2所應用,如果將這個引用傳入到了一個異步線程署恍,該線程的生命周期與Activity的生命周期不一致的時候崎溃,就會導致內(nèi)存泄露。

  • Static變量造成內(nèi)存泄露

1. 界面類的靜態(tài)化: 靜態(tài)Activity
  2. 界面中View的靜態(tài)化: 靜態(tài)View
  界面中View的靜態(tài)化一定會導致頁面內(nèi)存泄露盯质。界面中的View都是持有界面引用的袁串,靜態(tài)變量的生命周期與整個app的生命周期一致。
  3. 非靜態(tài)內(nèi)部類的靜態(tài)化
  具體的 如下所示:

public class MainActivity extends AppCompatActivity {  

    private static Drawable sDrawable;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView lableView = new TextView(this);
    if(sDrawable == null) {
        sDrawable = getDrawable(R.drawable.icon);       
    }
    labelView.setBackgroundDrawable(sDrawable);
        setContentView(lableView);
    }
}  

View的setBackgroundDrawable()的源碼如下所示:

public void setBackgroundDrawable(Drawable background) {
        ...

        if (background != null) {
            ...

            background.setCallback(this);
            ...
        } else {
            ...
        }

        ...
}

其中有一個background.setCallback(this);呼巷,所以這就導致這個靜態(tài)變量指向的對象又持有了TextView這個對象的引用囱修,TextView持有的確實整個Activity的引用。這樣就導致了內(nèi)存泄露王悍。

我們再來看一個例子:

public class MainActivity extends AppCompatActivity {
    private static InnerClass sInnerClass;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_leak);
        sHello = new Hello();
    }
    public class InnerClass {}
}  

靜態(tài)的非靜態(tài)內(nèi)部類對象sInnerClass持有了外部Acitivity的引用破镰,當屏幕發(fā)生變化時,不會被釋放。

  • <font size = 5>資源沒有關(guān)閉</font>
      1. Cursor游標沒有關(guān)閉
      數(shù)據(jù)庫中才操作經(jīng)常碰到cursor鲜漩。
      2. InputStream源譬、OutputStream等沒有關(guān)閉
      文件讀寫、Socket讀寫等經(jīng)常碰到
      3. 注冊的廣播等沒有unRegister
      4. 一些CallBack的Listener沒有被清除孕似,舉例:
void registerListener() {
    SensorManager sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
    Sensor snedor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
    sensorManager.registerListneer(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
}

getSystemService負責執(zhí)行某些后臺任務踩娘,或為硬件提供接口,如果context對象想要在服務內(nèi)部的事件發(fā)生時被通知喉祭,需要注冊監(jiān)聽器养渴。然而這讓服務持有了activity的引用,如果activity銷毀時沒有取消注冊泛烙,那么你的activity就泄露了厚脉。

  • View添加到?jīng)]有刪除機制的容器中

  • 屬性動畫導致的內(nèi)存泄露
      如果你設(shè)置你的動畫為無限循環(huán),而且沒有在onDestroy中停止該動畫胶惰,那么動畫會一直播放下去傻工,Activity的View會被動畫吃持有,而View持有了Activiy孵滞。從而導致內(nèi)存泄露中捆。

  • <font size = 5>過期引用</font>

當一個數(shù)組擴容后又被縮減,比如size從0->200->100(一個棧先增長坊饶,后收縮)泄伪,那么元素的index>=100的那些元素(被Pop掉的)都算是過期的元素,那些引用就是過期的引用(永遠不會再被接觸的應用)-來自Effective Java

public Object pop(){
      if(size==0) throw new EmptyStackException();
      Object result = elements[--size];
     elements[size] = null; //消除過期引用
     return result;
}

由于過期引用的存在匿级,GC并不會去回收他們蟋滴,我們需要手動的釋放他們。

內(nèi)存溢出和內(nèi)存的查看方法

  • 使用第三方開源庫

LeakCanary
在這里就不做具體的介紹了痘绎。網(wǎng)上的使用demo:
leakCanary Demo

  • adb shell命令

通過以下命令可以查看你APP的內(nèi)存使用情況已經(jīng)Activity和View等的個數(shù)情況津函,具體的

adb shell dumpsys meminfo packagename

其中,packagename就是你程序的報名孤页,具體的示例尔苦,如下圖所示:

dumpsysmeminfo.png

如上圖所示:
  上面部分顯示的是你的app所占用的內(nèi)存總數(shù)(主要是看TOTAL,內(nèi)存所實際占用的值)
  下面的部分可以看到你的一些對象的個數(shù):如Views行施、Activities等允坚。
當你進入一個acitivity的時候,activity的個數(shù)會增加蛾号,退出后會減少稠项,如果只增加、不減少鲜结,就說明出現(xiàn)了內(nèi)存泄露的問題展运。 (經(jīng)過實際的測試斩芭,這個對有些手機,好不管用乐疆,就算我寫個demo:只有一個Activity划乖,什么也沒有做,進來挤土、退出琴庵、進來、activities個數(shù)會變大仰美,不會立即變小迷殿,需要等一段時間才會變小)

  • DDMS

DDMS是Android開發(fā)環(huán)境中的Dalvik虛擬機(andoid4.4之前,4.4及其之后引入了ART虛擬機)調(diào)試監(jiān)控服務咖杂。

1. update heap

ddms_update_heap.png

對一個activity進入退出反復多次看data object是否穩(wěn)定在一個范圍
  2. MAT(Memory Analyzer Tool)

ddms_hprof.png

dump hprof file : 點擊后等待一會庆寺,會生成一個hprof文件。插件版本的MAT可以直接打開該文件诉字,否則需要進行一步轉(zhuǎn)換操作懦尝。 提供了這個工具 hprof-conv (位于 sdk/tools下), 轉(zhuǎn)換命令如下所示:

./hprof-conv xxx-a.hprof xxx-b.hprof 

最后通過DDMS-File-open,打開的hprof文件即可進行分析內(nèi)存泄露相關(guān)陵霉。

內(nèi)存優(yōu)化建議

  • 了解你機器的內(nèi)存情況

通過以下代碼可以查看每個進程可用的最大內(nèi)存踊挠,即heapgrowthlimit值

ActivityManager actManager = getApplicationContext.getSystemService(Context.ACTIVITY_SERVICE);s int memClass = actManager.getMemeoryClass(); //以M為單位

通過以下代碼可以獲取 應用程序的最大可用內(nèi)存

long maxMemory = Runtime.getRuntime().maxMemeory(); //以字節(jié)為單位

兩者的區(qū)別:
  單位不一致 前者以M為單位效床,后者以字節(jié)為單位剩檀。
  具體的以lenovo的一款手機(S850T谨朝, Android版本為4.4.2)為例: 經(jīng)過測試兩者得到的值一致均是128M。

使用場景
  當你進行圖片加載的時候,都會使用到LRUCache图谷,初始化的時候設(shè)置緩存的大小便贵。一般來說都設(shè)置為當前最大內(nèi)存的1/8,如果你就是一個圖片應用你直接1/4也可以。

long cacheSize = Runtime.getRuntime().maxMemeory();
mLruCache = new LruCache<String, Bitmap>(cacheSize)
        {
            @Override
            protected int sizeOf(String key, Bitmap value)
            {
                return value.getRowBytes() * value.getHeight();
            };
        };
  • 當界面不可見利耍、內(nèi)存緊張的時候釋放內(nèi)存

android4.0(包含4.0)之后引入了onTrimMemory(int level)(4.0之前為onLowMemory) 盔粹,系統(tǒng)會根據(jù)不同的內(nèi)存狀態(tài)來毀掉舷嗡,參數(shù) level 代表了你app的不同狀態(tài),Application捻脖、Activity郎仆、Fragment、Service曙旭、ContentProvider均可以響應桂躏。具體如下:

TRIM_MEMORY_UI_HIDDEN: 應用程序被隱藏了,如按了Home或者Back導致UI不可見较沪,這個時候尸曼,我們應該釋放一些內(nèi)存控轿。

以下三個是我們的應用程序真正運行時的回調(diào):
  TRIM_MEMORY_RUNNING_MODERATE: 程序正常運行,并不會被殺掉冒签,但是手機的內(nèi)存有點低了钟病,系統(tǒng)可能開始根據(jù)LRU規(guī)則來殺死進程了。
  TRIM_MEMORY_RUNNING_LOW: 程序正常運行档悠,并不會被殺掉,但是手機內(nèi)存非常的低了辖所,應該釋放一些資源了惰说,否則影響性能缘回。
  TRIM_MEMORY_RUNNING_CRITICAL: 程序正在運行吆视,但是系統(tǒng)已經(jīng)根據(jù)LRU殺死了大部分緩存的進程了,此時我們需要釋放內(nèi)存啦吧,否則系統(tǒng)可能會干掉你拙寡。

以下三個是當應用程序是緩存時候的回調(diào):
  TRIM_MEMORY_BACKGROUND: 內(nèi)存不足肆糕,并且該進程是后臺進程诚啃。
  TRIM_MEMORY_MODERATE: 內(nèi)存不足,并且該進程在后臺進程列表的中部。
  TRIM_MEMORY_COMPLETE:內(nèi)存不足造垛,并且該進程在后臺進程列表的最后一個魔招,馬上就要被清理了,這個時候應該把一切盡可能釋放的都釋放掉筋搏。

通常在我們開始進行架構(gòu)設(shè)計的時候仆百,就要考慮到哪些東西是要常駐的,哪些東西是緩存后要被清理奔脐, 一般情況下俄周,以下資源都要被清理:
緩存:包括文件緩存、圖片的緩存髓迎、比如第三方圖片緩存庫峦朗。
一些動態(tài)生成的View: 比如一般應用的圖片輪播View,在你的應用隱藏后排龄,根本不需要輪播波势。

案例分析:
  1. LRUCache緩存的清理方式:trimToSize()接口可以重新設(shè)置緩存的大小。evictAll()接口可以清楚所有的LRUCache緩存內(nèi)容橄维。
  2. 暴力清理界面中的View

  • 圖片資源的壓縮
      1. res中資源到壓縮: 使用有損壓縮工具尺铣,比如:tinyPng,壓縮后的圖片肉眼根本看不出來争舞,壓縮率可以達到50%以上凛忿。
      2. BitmapFactory的壓縮。
      通過BitmapFactory的Options設(shè)置竞川,降低采樣率店溢,壓縮圖片到適合的大小,同時注意使用若引用和緩存機制委乌。
      Bitmap.Config設(shè)置圖片的格式為RGB565床牧,這個設(shè)置肉眼是看不出色彩的丟失,而且比RGB8888占存小的多遭贸。
      使用BitmapFactory.Options.inBitmap字段戈咳。如果這個選項被設(shè)置,那么使用該Options 的decode方法將會嘗試復用一個已經(jīng)存在的bitmap來加載新的bitmap壕吹。這意味著bitmap的內(nèi)存將被復用除秀,避免分配和釋放內(nèi)存來提升性能。然后算利,使用inBitmap有一些限制册踩。特別是在Android4.4(API level19)之前,只有尺寸相同的bitmap才能使用該特性效拭。具體的見使用示例
      3. 將圖片資源放在合適的drawable目錄下楣黍。
  • 使用Android優(yōu)化過的類和集合
      1. SparseArrry<T>來替代HashMap<int, T>
      2. LongSparseArray<T>, key為long凤藏,替代HashMap<long, T>
      3. SimpleArrayMap<K, T>和ArrayMap<K,T>替代HashMap<K, T>, ArrayMap是通過時間來換取效率箩张,在數(shù)千之內(nèi)建議使用ArrayMap。
  • 避免創(chuàng)建不必要的對象

在短時間內(nèi)創(chuàng)建了大量的對象挤渔,然后有釋放肮街,這樣就引起了內(nèi)存抖動。頻繁的引起GC操作判导,會導致內(nèi)存的卡頓嫉父。
  1. 字符串的拼接:StringBuffer(非線程安全)和StringBuilder(線程安全)的使用
  2. 自定義View中不要在onDraw中定義畫筆等對象
  3. 在循環(huán)函數(shù)內(nèi)避免創(chuàng)建重復的對象沛硅,將多個函數(shù)都經(jīng)常用到的不可變對象拿出來統(tǒng)一進行初始化,在一開始寫的時候就要特別的注意绕辖,否則后邊修改起來很是麻煩(主要是再找到他很麻煩)
  4. 在循環(huán)的內(nèi)部不要使用try catch操作摇肌,將其拿到外面來。
  5. 不要在循環(huán)中進行文件的操作:比如判斷文件是否存在仪际,這相對是一個很耗時的操作

案例說明
  SimpleDateFromat是用來時間轉(zhuǎn)換的围小,一般的,開發(fā)者都會定義個專門用于時間轉(zhuǎn)化的static的函數(shù):

public static String paserTimeToYM(long time)
    {
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日", Locale.getDefault());
        return format.format(new Date(time));
    } 

假如你在for循環(huán)中調(diào)用此函數(shù)树碱。就不停的重復創(chuàng)建SimpleDateFromat對象肯适。你應該將對象創(chuàng)建拿出來,放在類中成榜,或者是重新定義一個時間轉(zhuǎn)換函數(shù)框舔,入慘為已經(jīng)創(chuàng)建好的SimpleDateFormat對象。
  還需要注意的是:假如你的循環(huán)量很大伦连,不建議在for循環(huán)中進行時間轉(zhuǎn)換雨饺,而是在你用到的時候才進行轉(zhuǎn)換,比如顯示出來惑淳。

  • 不要擴大變量的作用域
classs A
{
    private B mB;
    public A(B b) {
        this.mB = b;
        //就在構(gòu)造函數(shù)中進行了對mB進行了一些操作
    }
    //后續(xù)再也沒有用到過mB
}

class B
{
    public B() {
    }
    public static void main(String[] args)
    {
    }
}

如上所示的簡單代碼:類A的構(gòu)造函數(shù)中额港,傳入了類B的對象,并且類A中定義了成員變量mB歧焦,但是mB就在構(gòu)造函數(shù)中用了一下移斩,后續(xù)再也沒有用,在類A中mB的生命周期和A一致绢馍。本來mB的作用域就在構(gòu)造函數(shù)向瓷,結(jié)果擴大為整個類。

  • 不要讓生命周期比Activity長的對象持有Activity的引用

這樣的錯誤很多舰涌,比如:將Activity的Context傳給單例模式猖任,毫不知情的將Activity的Context傳給非靜態(tài)內(nèi)部類或者是匿名內(nèi)部類。

  • 盡量的使用Application的Context

Application的生命周期是整個app瓷耙,他會一直在朱躺。
  1. 在界面類中直接使用getApplicationContext。
  2. 在其他地方使用MyApplication(extends Application)的getInstance操作搁痛。如下所示:

public class MyApplication extends Application
{
    private static Context sContext;
 
    @Override
    public void onCreate()
    {
        Log.d(tag, "onCreate");
        sContext = this;
    }

    public static Context getAppContext()
    {
        return sContext;
    }
}

總之一句話:能使用Application的Context长搀,就不要使用Activity的。

  • 移除回調(diào)
      1. handler的removeCallbacksAndMessages(null)
      2. setXXXCallback(null)鸡典、 setXXXListener(null)源请,需要注意的是,要進行callback調(diào)用的地方就需要進行判斷了
  • 常量的使用

關(guān)于enum和static。Android強烈建議不要使用enum谁尸,他會使得內(nèi)存消耗變大為原來的2倍以上舅踪。

  • 使用代碼混淆剔除不需要的代碼

  • 請使用靜態(tài)內(nèi)部類+WeakReference的方式

非靜態(tài)內(nèi)部類和匿名內(nèi)部類會持有頁面的應用,請使用靜態(tài)內(nèi)部類症汹,并將頁面的引用通過WeakReference的方式傳遞過去硫朦。

  • 合理的使用多進程

android對單個進程都有一個內(nèi)存允許的最大內(nèi)存限制贷腕。加入你在你的app中又啟動一個進程背镇,這樣你的內(nèi)存限制就變?yōu)榱嗽瓉淼?倍。
  啟動多進程的方法很簡單泽裳,只需要在AndroidManifest.xml聲明的四大組件的標簽中增加"android:process"屬性即可瞒斩。
  進程分為兩種:私有進程和全局進程。私有進程在名稱簽名添加冒號即可涮总。
  但是多進程有一些需要注意的地方:
  1. Application的onCreate會被調(diào)用多次胸囱。一般程序會將程序的一些初始化的操作放在這里,這點需要注意瀑梗。
  2. 多進程之間的通訊必須使用AIDL接口烹笔,需要注意的一點是:AIDL之間傳遞大量數(shù)據(jù)是有一個限制的。 傳遞內(nèi)容過大會出現(xiàn):TransactionToolLargeException抛丽。官方文檔說明:最大的限制為1M谤职。
  3. 多進程導致 靜態(tài)成員、單例模式和SharedPreference 都變的不可靠亿鲜。
  4. 多進程之間傳遞數(shù)據(jù)的效率:有些手機在傳遞大量數(shù)據(jù)的時候允蜈,效率很差。
  5. 多進程傳遞對象需要實現(xiàn)序列化操作蒿柳。
  6. AIDL支持的數(shù)據(jù)類型:基本數(shù)據(jù)類型饶套;String和CharSequence;List僅僅支持ArrayList垒探,里面的每一個對象都必須支持序列化妓蛮,Map只支持HashMap,里面的key和value都必須支持序列化(必須被AIDL支持)圾叼。
  7. AIDL服務端可以使用CopyOnWriteArrayList和ConcurrentHashMap來進行自動線程同步蛤克,客戶端拿到的依然是ArrayList和HashMap。
  8.AIDL服務端和客戶端之間做監(jiān)聽器褐奥,服務端需要使用RemoteCallbackList咖耘,否則客戶端的監(jiān)聽器無法收到通知(因為服務端實質(zhì)還是一份新的序列化后的監(jiān)聽器實例,并不是客戶端那份)撬码。
  9.客戶端調(diào)用遠程服務方法時儿倒,因為遠程方法運行在服務端的binder線程池中,同時客戶端線程會被掛起,所以如果該方法過于耗時夫否,而客戶端又是UI線程彻犁,會導致ANR,所以當確認該遠程方法是耗時操作時凰慈,應避免客戶端在UI線程中調(diào)用該方法汞幢。同理,當服務器調(diào)用客戶端的listener方法時微谓,該方法也運行在客戶端的binder線程池中森篷,所以如果該方法也是耗時操作,請確認運行在服務端的非UI線程中豺型。另外仲智,因為客戶端的回調(diào)listener運行在binder線程池中,所以更新UI需要用到handler姻氨。

我們將在進程常駐中進行簡單的示例分析钓辆,實現(xiàn)多進程的相互喚醒操作。

  • 請不要使用注解框架

程序注解框架極大的方便了程序開發(fā)者肴焊,不需要開發(fā)者大量的寫findViewById(), setOnclickListener()等方法前联,但是程序注解框架是將類中的所有相關(guān)方法都緩存在內(nèi)容中不會釋放,這些內(nèi)存就會越來越大娶眷,從而得不到釋放似嗤。而且一般程序注解方法都是用到了Java的反射機制。這個是不建議使用的(雖然有時候反射不得不使用)茂浮。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末双谆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子席揽,更是在濱河造成了極大的恐慌顽馋,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幌羞,死亡現(xiàn)場離奇詭異寸谜,居然都是意外死亡,警方通過查閱死者的電腦和手機属桦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門熊痴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人聂宾,你說我怎么就攤上這事果善。” “怎么了系谐?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵巾陕,是天一觀的道長讨跟。 經(jīng)常有香客問我,道長鄙煤,這世上最難降的妖魔是什么晾匠? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮梯刚,結(jié)果婚禮上凉馆,老公的妹妹穿的比我還像新娘。我一直安慰自己亡资,他們只是感情好澜共,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沟于,像睡著了一般咳胃。 火紅的嫁衣襯著肌膚如雪植康。 梳的紋絲不亂的頭發(fā)上旷太,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音销睁,去河邊找鬼供璧。 笑死,一個胖子當著我的面吹牛冻记,可吹牛的內(nèi)容都是我干的睡毒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冗栗,長吁一口氣:“原來是場噩夢啊……” “哼演顾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起隅居,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钠至,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胎源,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棉钧,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年涕蚤,在試婚紗的時候發(fā)現(xiàn)自己被綠了宪卿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡万栅,死狀恐怖佑钾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烦粒,我是刑警寧澤休溶,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響邮偎,放射性物質(zhì)發(fā)生泄漏管跺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一禾进、第九天 我趴在偏房一處隱蔽的房頂上張望豁跑。 院中可真熱鬧,春花似錦泻云、人聲如沸艇拍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卸夕。三九已至,卻和暖如春婆瓜,著一層夾襖步出監(jiān)牢的瞬間快集,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工廉白, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留个初,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓猴蹂,卻偏偏與公主長得像院溺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子磅轻,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

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