Jetpack核心架构组件源码解析系列(1):Lifecycle运用与原理及源码分析

前言

Jetpack 是一个由多个库组成的套件,可帮助开发者遵循最佳做法,减少样板代码。如果项目采用 MVVM 架构,那么 Jetpack 里面的架构相关的组件就是为MVVM 量身定制的,而且现在面试Jetpack也是必问项,但是很多开发者对Jetpack中的一些核心组件都只停留在会用的阶段,对其原理及源码却是一知半解甚至根本没了解过,因此整理了一个系列来帮助有需要的小伙伴理解Jetpack设计思想和原理

正文

什么是Lifecycle?Lifecycle解决了开发中的什么问题?

我们先来一段Lifecycle出现之前的Activity生命周期监听代码:

1、先定义一个接口:

package com.kuer.ke_livedata;

public interface LifecycleInterface {
    void onCreate();

    void onResume();

    void onStart();

    void onStop();

    void onDestroy();
    //...
}

2、定义实现类

package com.kuer.ke_livedata;

import android.util.Log;

public class LifecycleImpl implements LifecycleInterface {
    @Override
    public void onCreate() {
        Log.e("LifecycleImpl------>","onCreate");
    }

    @Override
    public void onResume() {
        Log.e("LifecycleImpl------>","onResume");
    }

    @Override
    public void onStart() {
        Log.e("LifecycleImpl------>","onStart");
    }

    @Override
    public void onStop() {
        Log.e("LifecycleImpl------>","onStop");
    }

    @Override
    public void onDestroy() {
        Log.e("LifecycleImpl------>","onDestroy");
    }
    
    //...
}

3、生命周期监听(绑定)

package com.kuer.ke_livedata;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;


public class MainActivity extends AppCompatActivity {
    LifecycleImpl lifecycle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lifecycle = new LifecycleImpl();
        lifecycle.onCreate();
    }


    @Override
    protected void onResume() {
        super.onResume();
        lifecycle.onResume();
    }

    @Override
    protected void onStart() {
        super.onStart();
        lifecycle.onStart();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        lifecycle.onDestroy();
    }

    @Override
    protected void onStop() {
        super.onStop();
        lifecycle.onStop();
    }
}

从以上代码可以看出,在以前监听Activity的生命周期变化是一件很麻烦的事情,而且如果逻辑复杂的话会显得代码特别的臃肿,耦合非常严重。

我们再来一段基于Lifecycle的Activity生命周期监听代码:

1、定义一个实现类实现LifecycleOwner接口(GenericLifecycleObserver是LifecycleOwner的子类,因为LifecycleOwner是空的,所以一般都是实现GenericLifecycleObserver)

package com.kuer.ke_livedata;

import android.annotation.SuppressLint;
import android.util.Log;

import androidx.lifecycle.GenericLifecycleObserver;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;

@SuppressLint("RestrictedApi")
public class Feel implements GenericLifecycleObserver {

    //每当组件的生命周期发生改变的时候都会进行回调
    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        Log.e("Feel----------->",event.name());
    }
}

2、将这个接口作为观察者通过Lifecycle与Activity绑定起来

package com.kuer.ke_livedata;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MainActivity.this.getLifecycle().addObserver(new Feel());
    }
}

简单的代码就能通过Feel对象监听MainActivity的生命周期变化,而且所有的处理逻辑不需要写在MainActivity中。Lifecycle中有多种观察者写法,这里就不一一例举了。

概念总结: Lifecycle其实就是一个生命周期中转站,当组件的生命周期发生改变时,会通知该组件所持有的Lifecycle(Lifecycle中采取了观察者模式,可以添加观察者),Lifecycle又会通知所有的观察者,观察者就可以做出相对应的逻辑处理。在整个过程中,观察者与MainActivity的耦合很低,而且不会给MainActivity造成多余的负担,达到了一个很好的解耦和瘦身的效果

Lifecycle源码分析

以下是Lifecycle的源码:

public abstract class Lifecycle {

    @MainThread
    public abstract void addObserver(@NonNull LifecycleObserver observer);

    @MainThread
    public abstract void removeObserver(@NonNull LifecycleObserver observer);

    @MainThread
    @NonNull
    public abstract State getCurrentState();

    @SuppressWarnings("WeakerAccess")
    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }

    @SuppressWarnings("WeakerAccess")
    public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;
        //对比的方法 比如:State.RESUMED.isAtLeast(State.CREATED),
        //对比State.RESUMED的序数值是否大于State.CREATED的序数值(序数值不懂百度)
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }
}

通过源码我们可以看出,Lifecycle是一个抽象类,其内部不仅包括了添加和移除观察者的方法,还包括了EventState枚举,这两个枚举中Event指向组件生命周期对应的事件,这些事件会映射到 ActivityFragment中的事件分发,而State是用来配合Event来保存组件的生命周期执行轨迹的(这个概念会在下面的状态机中详细讲解)。

既然Lifecycle是一个抽象类,那么肯定会提供有具体的实现,它的实现类就是LifecycleRegistry,以下是LifecycleRegistry的源码:

public class LifecycleRegistry extends Lifecycle {

    private static final String LOG_TAG = "LifecycleRegistry";

    //所有观察者的容器
    private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
            new FastSafeIterableMap<>();
   
   //当前状态
    private State mState;

    private final WeakReference<LifecycleOwner> mLifecycleOwner;

    private int mAddingObserverCounter = 0;

    private boolean mHandlingEvent = false;
    private boolean mNewEventOccurred = false;

   
    private ArrayList<State> mParentStates = new ArrayList<>();

   
    public LifecycleRegistry(@NonNull LifecycleOwner provider) {
        mLifecycleOwner = new WeakReference<>(provider);
        //当LifecycleRegistry对象被创建的好 初始化状态
        mState = INITIALIZED;
    }

    //改变状态的方法1  
    @SuppressWarnings("WeakerAccess")
    @MainThread
    public void markState(@NonNull State state) {
        moveToState(state);
    }

    //改变状态的方法2 
    public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }

    private void moveToState(State next) {
        //新状态和当前状态一样就返回
        if (mState == next) {
            return;
        }
        //更新当前状态
        mState = next;
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;
        //同步
        sync();
        mHandlingEvent = false;
    }

    private boolean isSynced() {
        if (mObserverMap.size() == 0) {
            return true;
        }
        State eldestObserverState = mObserverMap.eldest().getValue().mState;
        State newestObserverState = mObserverMap.newest().getValue().mState;
        return eldestObserverState == newestObserverState && mState == newestObserverState;
    }

    private State calculateTargetState(LifecycleObserver observer) {
        Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);

        State siblingState = previous != null ? previous.getValue().mState : null;
        State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
                : null;
        return min(min(mState, siblingState), parentState);
    }

    //添加观察者的方法
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        //将观察者和Lifecycle的状态进行包装,方便观察者回调
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        //将包装类放入map容器中
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }

    private void popParentState() {
        mParentStates.remove(mParentStates.size() - 1);
    }

    private void pushParentState(State state) {
        mParentStates.add(state);
    }

    @Override
    public void removeObserver(@NonNull LifecycleObserver observer) {

        mObserverMap.remove(observer);
    }

    /**
     * The number of observers.
     *
     * @return The number of observers.
     */
    @SuppressWarnings("WeakerAccess")
    public int getObserverCount() {
        return mObserverMap.size();
    }

    @NonNull
    @Override
    public State getCurrentState() {
        return mState;
    }

    //获取状态 ,当前组件的生命周期事件分发过来后
    //Lifecycle的状态机要处于的状态
    static State getStateAfter(Event event) {
        switch (event) {
            case ON_CREATE:
            case ON_STOP:
                return CREATED;
            case ON_START:
            case ON_PAUSE:
                return STARTED;
            case ON_RESUME:
                return RESUMED;
            case ON_DESTROY:
                return DESTROYED;
            case ON_ANY:
                break;
        }
        throw new IllegalArgumentException("Unexpected event value " + event);
    }

    private static Event downEvent(State state) {
        switch (state) {
            case INITIALIZED:
                throw new IllegalArgumentException();
            case CREATED:
                return ON_DESTROY;
            case STARTED:
                return ON_STOP;
            case RESUMED:
                return ON_PAUSE;
            case DESTROYED:
                throw new IllegalArgumentException();
        }
        throw new IllegalArgumentException("Unexpected state value " + state);
    }

    private static Event upEvent(State state) {
        switch (state) {
            case INITIALIZED:
            case DESTROYED:
                return ON_CREATE;
            case CREATED:
                return ON_START;
            case STARTED:
                return ON_RESUME;
            case RESUMED:
                throw new IllegalArgumentException();
        }
        throw new IllegalArgumentException("Unexpected state value " + state);
    }

    private void forwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
                mObserverMap.iteratorWithAdditions();
        while (ascendingIterator.hasNext() && !mNewEventOccurred) {
            //将数组的Entry拿出来,Entry中key就是观察者,Value就是Lifecycle的状态
            Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                pushParentState(observer.mState);
                //回调观察者
                observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
                popParentState();
            }
        }
    }

    private void backwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
                mObserverMap.descendingIterator();
        while (descendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                Event event = downEvent(observer.mState);
                pushParentState(getStateAfter(event));
                 //回调观察者
                observer.dispatchEvent(lifecycleOwner, event);
                popParentState();
            }
        }
    }

    // happens only on the top of stack (never in reentrance),
    // so it doesn't have to take in account parents
    private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            Log.w(LOG_TAG, "LifecycleOwner is garbage collected, you shouldn't try dispatch "
                    + "new events from it.");
            return;
        }
        while (!isSynced()) {
            mNewEventOccurred = false;
            // no need to check eldest for nullability, because isSynced does it for us.
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                //在里面会回调所有观察者
                backwardPass(lifecycleOwner);
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                //在里面会回调所有观察者
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

    static State min(@NonNull State state1, @Nullable State state2) {
        return state2 != null && state2.compareTo(state1) < 0 ? state2 : state1;
    }

    static class ObserverWithState {
        State mState;
        GenericLifecycleObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            mLifecycleObserver = Lifecycling.getCallback(observer);
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }
}

通过以上的代码我们可以大概猜出组件生命周期发生改变的适合是如何通知Lifecycle的,如下图: !

那么,我们通过源码来看一看,组件的生命周期变化的时候是如何通知Lifecycle的。

Lifecycle的实现类LifecycleRegistry是在Activity的父类ComponentActivity中被实例化的,所以我们开去ComponentActivity中看看,一下是ComponentActivity相关代码:

@RestrictTo(LIBRARY_GROUP)
public class ComponentActivity extends Activity implements LifecycleOwner {
    private SimpleArrayMap<Class<? extends ExtraData>, ExtraData> mExtraDataMap =
            new SimpleArrayMap<>();

    //1、
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    @RestrictTo(LIBRARY_GROUP)
    public void putExtraData(ExtraData extraData) {
        mExtraDataMap.put(extraData.getClass(), extraData);
    }

    @Override
    @SuppressWarnings("RestrictedApi")
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //2、
        ReportFragment.injectIfNeededIn(this);
    }

    @CallSuper
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        //3、
        mLifecycleRegistry.markState(Lifecycle.State.CREATED);
        super.onSaveInstanceState(outState);
    }

    @RestrictTo(LIBRARY_GROUP)
    public <T extends ExtraData> T getExtraData(Class<T> extraDataClass) {
        return (T) mExtraDataMap.get(extraDataClass);
    }

    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }

    @RestrictTo(LIBRARY_GROUP)
    public static class ExtraData {
    }
}

在注释1处LifecycleRegistry被创建了,在注释3处,将LifecycleRegistry的State设置为CREATED,注释2处的将ComponentActivity注入到ReportFragment中。正常来说,从以上结构来看,组件的生命周期事件应该是在ComponentActivity中被分发给LifecycleRegistry的,但实际上,并不是,而是由ReportFragment来进行分发的,所以接下来我们要进入ReportFragment中看看:

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class ReportFragment extends Fragment {
    private static final String REPORT_FRAGMENT_TAG = "androidx.lifecycle"
            + ".LifecycleDispatcher.report_fragment_tag";
    public static void injectIfNeededIn(Activity activity) {
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            manager.executePendingTransactions();
        }
    }
    static ReportFragment get(Activity activity) {
        return (ReportFragment) activity.getFragmentManager().findFragmentByTag(
                REPORT_FRAGMENT_TAG);
    }
   ...
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatchCreate(mProcessListener);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatchResume(mProcessListener);
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    //...
    private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
         //判断当前组件是否实现了LifecycleRegistryOwner接口
         //LifecycleRegistryOwner是LifecycleOwner的子类
         //两者区别的它们的getLifecycle()方法返回的类型不一样
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }
        //判断当前组件是否实现了LifecycleOwner接口
        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }
    //...
}

通过以上代码我们可以看出,在ReportFragment的各个生命周期的方法中,会调用dispatch()方法,而dispatch方法中就会将组件相对应的事件分发给Lifecycle,最终会在LifecycleRegistry进行状态更新以及通知所有的观察者。

以上就是Lifecycle感知组件生命周期,并通知观察者的流程。

Lifecycle中的状态机概念

为什么会存在状态机的概念呢?*因为Lifecycle中的观察者可能会在Activity的任意一个生命周期中添加进来,所以*为了避免后面添加的观察者错失组件前面的生命周期,就用状态机中的状态配合组件的生命周期的事件来记录Activity的生命周期轨迹。大家还记得Lifecycle中的两个枚举类吗,那就是状态机用来记录Activity的生命周期记录轨迹的。我们可以先来看一下这张图(紫色字体为Lifecycle.State枚举类中的常量,黑色字为Lifecycle.EVENT中的常量,对应的是组件的生命周期)**:

Activity等组件的生命周期发生改变的后,就会把相对应的生命周期传到LifecycleLifecycle会将组件的生命周期和State枚举类中的枚举常量对应保存起来并与每个观察者进行绑定,具体对应如上图。在Lifecycle中,为了更好的了解组件的生命周期轨迹,将组件的生命周期分为两个概念,第一个概念叫“生命周期的前进”,指的是onCreate->onStart->onResume这个过程,第二个概念叫 “生命周期的倒退” ,指的是onPause->onStop->onDestroy这个过程(注意,前进和后退不需要三个方法都调用,两个方法调用也可以)。接下来我们聊聊Lifecycle.State的作用:

 public enum State {
        
        DESTROYED,


        INITIALIZED,

 
        CREATED,

    
        STARTED,

    
        RESUMED;

        //比较枚举常量的序数大小的方法
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }

Lifecycle.State会保存在观察者中去的,其意义是,当我们在onStart方法中注册一个观察者时,为了让这个观察者不错过之前执行过了的onCreate生命周期,在添加观察者的时候会通过一段代码来弥补:

 @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        //观察者刚注册的时候,初始化的状态INITIALIZED
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        //把观察者和状态封装在一起,这样能更好的绑定
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        //如果观察者的状态和Lifecycle不同步,就先同步,在同步的好就会进行回调观察者
        //如果我们是在onStart中注册的观察者,肯定不同步(这里建议去自行断点测试下)
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }
        //...
    }

在以上代码中会对比观察者和Lifecycle保存的组组件的生命周期是否同步,如果不同步,就先进行同步,同步的时候就会回调观察者。以下是代码测试:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();
        MainActivity.this.getLifecycle().addObserver(new Feel());
    }
}
@SuppressLint("RestrictedApi")
public class Feel implements GenericLifecycleObserver {
    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        Log.e("Feel----------->","Activity:"+event.name()+"------Lifecycle.State:------->"+source.getLifecycle().getCurrentState());
    }
}

一下是输出日志:

2022-08-04 16:01:23.745 26582-26582/com.kuer.ke_livedata E/Feel----------->: Activity:ON_CREATE------Lifecycle.State:------->STARTED
2022-08-04 16:01:23.745 26582-26582/com.kuer.ke_livedata E/Feel----------->: Activity:ON_START------Lifecycle.State:------->STARTED
2022-08-04 16:01:23.745 26582-26582/com.kuer.ke_livedata E/Feel----------->: Activity:ON_RESUME------Lifecycle.State:------->RESUMED

总结:通过以上代码,就可以了解到Lifecycle的状态机的作用了,其实就是用来同步组件和Lifecycle和观察者的生命周期状态的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容