Activity源碼分析

Activity 源碼解析

Activity是Android里非常重要的一個組件。東西非常多,如果本文有沒有覆蓋到要糊,但你又覺得非常重要的部分,歡迎給我反饋妆丘。如果你發(fā)現(xiàn)了任何錯誤也歡迎給我反饋锄俄。(Email:zhxilong2015@gmail.com

以下全部基于Android 8.0 Api26的源碼分析。不同版本可能稍有不同勺拣。但整個基本原理其實(shí)是完全一樣的奶赠。
既然是源碼分析,所以這里不會去做功能分析宣脉,比如Activity都有什么功能车柠,startActivity怎么調(diào)用剔氏,怎么給Activity添加專場動畫等塑猖,這里會著重分析Activity從創(chuàng)建到結(jié)束,都經(jīng)過了哪些過程谈跛,這些過程代碼都在什么位置羊苟,Activity是在哪里new出來的,生命周期為什么能被回調(diào)等等這些感憾,本文會跟隨著Android系統(tǒng)的代碼執(zhí)行順序蜡励,一步步從Activity被創(chuàng)建分析到Activity被銷毀。大致會從以下幾個部分來介紹,有一定的閱讀門檻:

  • Android消息機(jī)制
  • ActivityThread介紹
  • Activity如何收到消息
  • Activity的生命周期事件
  • Activity結(jié)束
  • 總結(jié)

1. 簡介

Activity是Android的四大組件之一凉倚,光注釋都五六百行兼都。大致從注釋能看到Activity本身是為UI服務(wù)的,介紹了生命周期和一些常用功能稽寒。更詳細(xì)的還需要從源碼層面分析扮碧。

2. 源碼分析

1.Android消息機(jī)制

除了類似單片機(jī)這種特殊的操作系統(tǒng),大部分操作系統(tǒng)都會有消息機(jī)制杏糙。消息機(jī)制把軟件需要執(zhí)行的代碼都包裝成消息慎王。有了消息機(jī)制可以很方便的讓軟件對外界操作進(jìn)行實(shí)時響應(yīng)。一個RecyclerView宏侍,你上滑一下赖淤,RecyclerView滑動還沒有結(jié)束你這時候可以按住RecyclerView,RecyclerView會實(shí)時響應(yīng)你的操作讓滑動立刻停止谅河。怎么做到的咱旱?其實(shí)就是消息機(jī)制。RecyclerView的滑動被分割成了若干個消息绷耍,每個消息都移動一小段距離莽龟,這時候你突然按住RecyclerView,你的操作會被立即插入到消息循環(huán)锨天,這時候不再執(zhí)行移動的操作毯盈,而是響應(yīng)你按住這個操作,讓RecyclerView立刻停止病袄。用戶看到的效果就是App實(shí)時響應(yīng)了用戶的請求搂赋,沒有因?yàn)锳pp當(dāng)前正在滑動RecyclerView而用戶等待動畫結(jié)束。

在Android中實(shí)現(xiàn)消息機(jī)制的就是Handler益缠、Message脑奠、MessageQueue、Looper這四兄弟幅慌。任何操作都被封裝成Message被添加到MessageQueue中宋欺,Looper負(fù)責(zé)消息的循環(huán),拿到消息后交給Handler來處理胰伍。
這里之所以要簡單介紹消息機(jī)制齿诞,主要就是Activity的各種事件本質(zhì)來源其實(shí)都是Handler消息。知道消息機(jī)制骂租,接下來就會很容易理解Activity的一系列事件回調(diào)祷杈。

2.ActivityThread介紹

Java可以很方便的隨時Dump當(dāng)前的方法棧,可以看到當(dāng)前代碼是經(jīng)過了怎樣的方法棧被調(diào)到的渗饮。

      at android.app.Activity.performCreate(Activity.java:6975)
      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2784)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2906)
      at android.app.ActivityThread.-wrap11(ActivityThread.java:-1)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1605)
      at android.os.Handler.dispatchMessage(Handler.java:105)
      at android.os.Looper.loop(Looper.java:172)
      at android.app.ActivityThread.main(ActivityThread.java:6637)
      at java.lang.reflect.Method.invoke(Method.java:-1)
      at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

在任意一個Activity的onCreate加個斷點(diǎn)但汞,可以得到以上方法棧數(shù)據(jù)宿刮。或者每當(dāng)App崩潰的時候也會有類似數(shù)據(jù)被輸出到Log私蕾,再或者也可以通過

        Thread.currentThread().getStackTrace();

得到方法棧自己輸出到Logcat僵缺。除了關(guān)注自己代碼部分,可能很少會有人去關(guān)注下面這些方法踩叭。下面這些方法你有看到Looper.loop嗎谤饭?這不是我們的消息循環(huán)嗎?loop是被誰調(diào)用的懊纳?ActivityThread.main揉抵。ActivityThread的main方法就是Android App的入口代碼(這個入口是被ActivityManagerService定義的,那可以在ActivityManagerService中找到相關(guān)代碼嗤疯,這里不做詳細(xì)介紹)冤今。ActivityThread源碼包含在SDK中(如果你雙擊Shift輸入ActivityThread IDE沒有找到這個類的話,你可以先找到Activity類茂缚,然后在Activity源碼中find查找ActivityThread戏罢,然后通過快捷鍵跟進(jìn)ActivityThread源碼)。
定位到main方法:

public class ActivityThread{

    ...

    private void attach(boolean system) {
        if (!system) {
            ...
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
        }
    }

    ...

    public static void main(String[] args) {
        ......
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
}

基本上做了兩件事脚囊,初始化ActivityThread(注意有個mgr.attachApplication(mAppThread)注冊mAppThread)龟糕,然后在main方法最后進(jìn)入了Looper.loop的消息循環(huán),因?yàn)檫@個循環(huán)是不會結(jié)束的悔耘,所以最后一個異常正常情況下是不會被執(zhí)行到的讲岁。當(dāng)然你可以通過

        Looper.getMainLooper().quit();

強(qiáng)行讓主線程消息循環(huán)結(jié)束。

看到這里我們應(yīng)該明白衬以,在App初始化完成后缓艳,執(zhí)行的代碼都會進(jìn)入到Looper中執(zhí)行,所以就很容易理解看峻,其實(shí)我們的Activity創(chuàng)建阶淘,Activity生命周期回調(diào)也將是Handler消息的形式。

在ActivityThread類中有個內(nèi)部類H互妓,繼承自Handler溪窒。H類定義了很多類型的int,看名字其實(shí)很容易跟生命周期回調(diào)對應(yīng)起來冯勉。

3.Activity如何收到消息

前面我們知道Looper.loop之后澈蚌,App要想執(zhí)行代碼,肯定是通過HandlerMessage的形式珠闰。那么Activity在創(chuàng)建前一定是收到了一個HandlerMessage惜浅。找到處理Message的H類,里面有個LAUNCH_ACTIVITY伏嗜。

private class H extends Handler {
    public static final int LAUNCH_ACTIVITY         = 100;
    ...
    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                r.packageInfo = getPackageInfoNoCheck(
                        r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
            ...
        }
        ...
    }
}

在handleMessage時候通過handleLaunchActivity來處理LAUNCH_ACTIVITY消息坛悉。
在分析處理部分的代碼前,我們回過來想下LAUNCH_ACTIVITY消息是被誰發(fā)出的呢承绸?find搜下裸影。

class ActivityThread{
    ...
    private class ApplicationThread extends IApplicationThread.Stub {
        ...
        @Override
        public final void scheduleLaunchActivity(...){
            ...
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
        ...
    }
    ...
}

保留關(guān)鍵代碼就是上面的結(jié)構(gòu)。到這里創(chuàng)建Activity的代碼军熏,其實(shí)都涉及到了轩猩。為了更清楚的理解,我們再把代碼順序梳理下荡澎,就是下面的代碼從上到下均践。我用“>數(shù)字”標(biāo)出了代碼執(zhí)行順序。順著數(shù)字順序可以很清晰的理解這個過程摩幔。

public class ActivityThread{

    ...
    // >1
    // App入口
    public static void main(String[] args) {
        ......
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        // >2
        // 初始化一些必要數(shù)據(jù)
        thread.attach(false);
        // >5
        // 啟動消息循環(huán)
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

    ...
    // >3
    private void attach(boolean system) {
        if (!system) {
            ...
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                // >4
                // 注冊binder到遠(yuǎn)端ActivityManagerService
                // 注冊完成后mAppThread就可以接收ActivityMangerService跨進(jìn)程發(fā)過來的消息了彤委。
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
        }
    }

    ...

    private class ApplicationThread extends IApplicationThread.Stub {
        ...
        // >6
        // 遠(yuǎn)端ActivityManagerService通過Binder跨進(jìn)程通信,
        // 調(diào)到這個方法或衡,當(dāng)前在App的Binder線程焦影。
        @Override
        public final void scheduleLaunchActivity(...){
            ...
            // >7
            // 由于此時在Binder線程,所以不能直接調(diào)用handleLaunchActivity方法封断。
            // 需要通過Handler跨線程通信給主線程發(fā)LAUNCH_ACTIVITY消息斯辰。
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
        ...
    }
    ...

    private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;

        ...
        // >8
        // 主線程收到LAUNCH_ACTIVITY消息。
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    // 處理LAUNCH_ACTIVITY消息
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    // >9
                    // 打開Activity
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                ...
            }
            ...
        }
        ...
    }
}

LAUNCH_ACTIVITY事件從scheduleLaunchActivity發(fā)出坡疼。那scheduleLaunchActivity被誰調(diào)用彬呻?還記得前面初始化ActivityThread我說的(注意有個setApplicationObject注冊mAppThread)嗎?ApplicationThread繼承自IApplicationThread.Stub柄瑰,看到Stub是不是覺得很熟悉废岂?就是Binder跨進(jìn)程通信。
在Looper進(jìn)入loop循環(huán)前狱意,調(diào)用了ActivityThread.attach方法湖苞,在attach中將ApplicationThread綁定到了系統(tǒng)的ActivityManagerService進(jìn)程。此時只要ActivityManagerSercice通過跨進(jìn)程通信給App發(fā)LAUNCH_ACTIVITY消息详囤,那么ApplicationThread的scheduleLaunchActivity將收到LAUNCH_ACTIVITY消息财骨,但是因?yàn)榇藭rApplicationThread是在Binder線程,所以此時將通過Handler跨線程給主線程發(fā)LAUNCH_ACTIVITY藏姐,主線程的H類的handlerMessage收到LAUNCH_ACTIVITY隆箩,然后調(diào)用handleLaunchActivity(這里梳理了下系統(tǒng)是如何收到打開Activity消息的,后面還會把怎么發(fā)出消息即startActivity也給分析下)羔杨。

3.Activity的生命周期事件

把App如何接收LAUNCH_ACTIVITY消息梳理完了捌臊,下面就要開始Activity是怎么被new的,以及Activity是如何收到各種聲明周期事件的兜材。還是老樣子理澎,我把Activity創(chuàng)建和生命周期相關(guān)關(guān)鍵代碼貼出來逞力,并用“>數(shù)字”來標(biāo)注執(zhí)行順序。

    // >1
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        ...

        // Initialize before creating the activity
        WindowManagerGlobal.initialize();
        // 創(chuàng)建Activity以及處理生命周期
        // >2
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            ...
            // >12
            // onResume
            handleResumeActivity(...);
            ...
            }
        } else {
            ...
        }
    }

    // >3
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            // >4
            // 創(chuàng)建Activity實(shí)例
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ...
        } catch (Exception e) {
            ...
        }
        try {
            ...
            activity.attach(...);
            ...
            // >7
            // onCreate
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            ...
            // >8
            // onStart
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }
            // >9
            // onRestore
            if (!r.activity.mFinished) {
                if (r.isPersistable()) {
                    if (r.state != null || r.persistentState != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                r.persistentState);
                    }
                } else if (r.state != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            // >10
            // onPostCreate
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onPostCreate()");
                }
            }
            r.paused = true;
            // >11
            // 持有Activity實(shí)例的r被添加到mActivities中糠爬。
            mActivities.put(r.token, r);
            ...
        } catch (Exception e) {
            ...
        }
        ...
    }
    // >13
    final void handleResumeActivity(...) {
        ...
        // >14
        // onResume
        r = performResumeActivity(token, clearHide, reason);
        if (r != null) {
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                // 不可見寇荧,后面會通過activity.makeVisible()恢復(fù)可見
                decor.setVisibility(View.INVISIBLE);
                ...
                if (a.mVisibleFromClient) {
                    if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        // >17
                        // 被添加到WindowManager
                        wm.addView(decor, l);
                    } else {
                        ...
                    }
                }
                ...
                        // 恢復(fù)Activity可見
                        r.activity.makeVisible();
                ...
            ...
            }
        }
    }
    ...
    // >15
    // onResume
    public final ActivityClientRecord performResumeActivity(...) {
        ...
        if (r != null && !r.activity.mFinished) {
            ...
            try {
                ...
                // >16
                // onResume
                r.activity.performResume();
                ...
            } catch (Exception e) {
                ...
            }
    }
public class Instrumentation {
    ...
    // >5
    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        // >6
        // 通過反射創(chuàng)建Activity實(shí)例
        return (Activity)cl.loadClass(className).newInstance();
    }
    ...
}

我已經(jīng)用“>數(shù)字”把主要的事件執(zhí)行順序回調(diào)貼出來了。按照順序可以很清晰的看到一個Activity是怎么被創(chuàng)建出來的执隧,以及創(chuàng)建出來后比如onCreate揩抡、onStart等各個生命周期是如何收到回調(diào)事件的。收到LAUNCH_ACTIVITY消息后镀琉,ActivityManagerService不需要再發(fā)送RESUME_ACTIVITY消息峦嗤,LAUNCH_ACTIVITY處理過程會直接處理掉onStart,onResume屋摔。
那假如我此時按下Home鍵后烁设,App要收到onPause消息,我們來分析下這個過程凡壤。
按下Home后署尤,ActivityManagerService將通過跨進(jìn)程通信給App發(fā)送PAUSE_ACTIVITY的消息。

public final class ActivityThread {
    private class ApplicationThread extends IApplicationThread.Stub {
        ...
        // >1
        // 當(dāng)前在Binder線程收到ActivityManagerService跨進(jìn)程通信
        public final void schedulePauseActivity(...) {
            ...
            // >2
            // 此時在Binder亚侠,給主線程發(fā)PAUSE_ACTIVITY的消息
            // 如果是finished就發(fā)送PAUSE_ACTIVITY_FINISHING消息曹体。
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);
        }
        ...
    }
 
    private class H extends Handler {
        // >3
        // 此時進(jìn)入主線程
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case PAUSE_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    // >4
                    // onPause∏
                    handlePauseActivity((IBinder) args.arg1, false,
                            (args.argi1 & USER_LEAVING) != 0, args.argi2,
                            (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
            }
        }
    }
    // >5
    private void handlePauseActivity(...) {
        ...
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                // >6
                // 見過這個生命周期嗎?
                performUserLeavingActivity(r);
            }
            // >8
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
            ...
        }
    }

    // >7
    final void performUserLeavingActivity(ActivityClientRecord r) {
        mInstrumentation.callActivityOnUserLeaving(r.activity);
    }

    // >9
    final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        // >10
        // 重載performPauseActivity
        return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
    }

    // >11
    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
        ...
        // >12
        // 回調(diào)onSaveInstanceState
        // Next have the activity save its current state and managed dialogs...
        if (!r.activity.mFinished && saveState) {
            callCallActivityOnSaveInstanceState(r);
        }

        // >13
        performPauseActivityIfNeeded(r, reason);

        ...
        // >16
        return !r.activity.mFinished && saveState ? r.state : null;
    }

    // >14
    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        ...

        try {
            ...
            // >15
            // 回調(diào)onPause
            mInstrumentation.callActivityOnPause(r.activity);
            ...
        } catch (...) {
            ...
        }
        r.paused = true;
    }
}

好了硝烂,onPause結(jié)束箕别。過程很簡單,順便還能學(xué)到一個回調(diào)performUserLeavingActivity滞谢。同樣的onResume過程跟onPause過程基本差不多串稀,這里就不再啰嗦了。
到了這里其實(shí)你應(yīng)該也就非常清楚了所有生命周期回調(diào)的先后順序狮杨,以及每個生命周期具體是怎么回調(diào)到Activity的母截。那么生命周期的介紹就算告一個段落了。

4.Activity的結(jié)束

這里再說下mActivies橄教。

public final class ActivityThread {
    ...
    // 在低版本上這里是用的HashMap
    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
    ...
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        mActivities.put(r.token, r);
        ...
    }
    ...
}

還記得前面在LaunchActivity的時候把持有Activity實(shí)例的ActivityClientRecord r被put到mActivities嗎清寇?Java不需要自己手動處理對象釋放,Java會通過自己的GC來釋放护蝶。那么Activity對象在創(chuàng)建后肯定需要一個對象來持有它华烟,否則Activity實(shí)例在GC時候就會被銷毀了。那么誰來持有Activity持灰?就是這里到mActivities盔夜。所有Activity被創(chuàng)建后都會被添加進(jìn)來,當(dāng)然與之對應(yīng)的就會在onDestory的時候從mActivities中移除。你可以嘗試用上面分析的過程去找下什么時候被移除的喂链。

3. 總結(jié)

Activity的東西非常多返十,但只要理解了其中的規(guī)律,就會很容易舉一反三衩藤。如果你看明白了這整個過程吧慢,就可以很輕松的通過H類定義的msg.what涛漂,找到App都能接受到多少種不同類型的系統(tǒng)回調(diào)赏表。這些回調(diào)有Activity的,也有Service的匈仗,也有Application的等等瓢剿。同樣的方法你可以很容易分析Service的消息處理過程,大家都在說Service onStartCommand是發(fā)生在主線程悠轩,那么為什么是主線程间狂?同樣的思路,你可以非常容易弄明白這個過程火架。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鉴象,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子何鸡,更是在濱河造成了極大的恐慌纺弊,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骡男,死亡現(xiàn)場離奇詭異淆游,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)隔盛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門犹菱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吮炕,你說我怎么就攤上這事腊脱。” “怎么了龙亲?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵陕凹,是天一觀的道長。 經(jīng)常有香客問我俱笛,道長捆姜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任迎膜,我火速辦了婚禮泥技,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘磕仅。我一直安慰自己珊豹,他們只是感情好簸呈,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著店茶,像睡著了一般蜕便。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贩幻,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天轿腺,我揣著相機(jī)與錄音,去河邊找鬼丛楚。 笑死族壳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的趣些。 我是一名探鬼主播仿荆,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坏平!你這毒婦竟也來了拢操?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤舶替,失蹤者是張志新(化名)和其女友劉穎令境,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坎穿,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡展父,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了玲昧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片栖茉。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖孵延,靈堂內(nèi)的尸體忽然破棺而出吕漂,到底是詐尸還是另有隱情,我是刑警寧澤尘应,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布惶凝,位于F島的核電站,受9級特大地震影響犬钢,放射性物質(zhì)發(fā)生泄漏苍鲜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一玷犹、第九天 我趴在偏房一處隱蔽的房頂上張望混滔。 院中可真熱鬧,春花似錦、人聲如沸坯屿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽领跛。三九已至乏德,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吠昭,已是汗流浹背喊括。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怎诫,地道東北人瘾晃。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓贷痪,卻偏偏與公主長得像幻妓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子劫拢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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