Glide的with()过程和Glide的生命周期的源码分析

  在Android开发中,或多或少你都会使用过很多的框架,但是没有一个框架会像Glide一样好用。Glide.with(context).load(url).into(imageView).一行代码解决了很多问题,今天我们就来深入Glide的源码,来看看这一行代码背后的故事。先从Glide的with()方法开始我们的探索。

with()过程分析

Glide类里面的with()方法

 public static RequestManager with(Context context) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(context);
    }
public static RequestManager with(Activity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }
public static RequestManager with(FragmentActivity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }
public static RequestManager with(android.app.Fragment fragment) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(fragment);
    }
/**
     * Begin a load with Glide that will be tied to the given {@link android.support.v4.app.Fragment}'s lifecycle and
     * that uses the given {@link android.support.v4.app.Fragment}'s default options.
     *
     * @param fragment The fragment to use.
     * @return A RequestManager for the given Fragment that can be used to start a load.
     */
public static RequestManager with(Fragment fragment) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(fragment);
    }

  Glide类里面有很多with()方法的重载,在with()方法中传入不同类型的参数,来调用不同的重载的with()方法。可以看到,Glide为
Activity和Fragment(android.app.Fragment和v4包下的Fragment)都提供Glide的使用。
  通过看Glide的这几个with()方法,可以发现里面都调用了RequestManageRetriever类的get()方法。

  • RequestManagerRetriever类:帮助拿到RequestManager对象,
    RequestManageRetriever类里面的get()方法
private static final RequestManagerRetriever INSTANCE = new RequestManagerRetriever();
public static RequestManagerRetriever get() {
        return INSTANCE;
    }

  这个RequestManagerRetriever类里面的get()方法是一个static的静态内部方法,返回一个静态RequestManagerRetriever对象,这是一个单例实现。
  在Glide类的这几个重载的with()方法中,首先都是先得到了RequestManagerRetriever对象,紧接着都调用了RequestManagerRetriever对象的带参数的实例get()方法,只不过不同的with()方法中传入RequestManagerRetriever类的get()方法的参数类型不同罢了。

RequestManagerRetriever类中

private RequestManager getApplicationManager(Context context) {
        // Either an application context or we're on a background thread.
        if (applicationManager == null) {
            synchronized (this) {
                if (applicationManager == null) {
                    // Normally pause/resume is taken care of by the fragment we add to the fragment or activity.
                    // However, in this case since the manager attached to the application will not receive lifecycle
                    // events, we must force the manager to start resumed using ApplicationLifecycle.
                    applicationManager = new RequestManager(context.getApplicationContext(),
                            new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
                }
            }
        }

        return applicationManager;
    }
public RequestManager get(Context context) {
        if (context == null) {
            throw new IllegalArgumentException("You cannot start a load on a null Context");
        } else if (Util.isOnMainThread() && !(context instanceof Application)) {
            if (context instanceof FragmentActivity) {
                return get((FragmentActivity) context);
            } else if (context instanceof Activity) {
                return get((Activity) context);
            } else if (context instanceof ContextWrapper) {
                return get(((ContextWrapper) context).getBaseContext());
            }
        }

        return getApplicationManager(context);
    }
public RequestManager get(FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            FragmentManager fm = activity.getSupportFragmentManager();
            return supportFragmentGet(activity, fm);
        }
    }
public RequestManager get(Fragment fragment) {
        if (fragment.getActivity() == null) {
            throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
        }
        if (Util.isOnBackgroundThread()) {
            return get(fragment.getActivity().getApplicationContext());
        } else {
            FragmentManager fm = fragment.getChildFragmentManager();
            return supportFragmentGet(fragment.getActivity(), fm);
        }
    }
public RequestManager get(Activity activity) {
        if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            android.app.FragmentManager fm = activity.getFragmentManager();
            return fragmentGet(activity, fm);
        }
    }
 public RequestManager get(android.app.Fragment fragment) {
        if (fragment.getActivity() == null) {
            throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
        }
        if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            return get(fragment.getActivity().getApplicationContext());
        } else {
            android.app.FragmentManager fm = fragment.getChildFragmentManager();
            return fragmentGet(fragment.getActivity(), fm);
        }
    }

  可以看到在RequestManagerRetriever类中,有很多get()实例方法的重载,归根结底的分为传入Application类型的和非Application类型的参数。
传入Application类型的参数时,就会调用getApplicationManager()方法。在这个方法中会生成RequestManager对象并返回,这个RequestManager对象就是Glide类的with()方法中所返回的。
传入非Application类型的参数时,会根据传入的是Activity,还是Fragment(android.app.Fragment和v4包下的Fragment)来调用不同的get()方法。这些get()方法中传入的参数类型不一样,但是这些get()方法中的大致处理流程是一致的。我们选一个传入v4包下的Fragment类型的get()方法来看。

传入v4包下的Fragment到RequestManagerRetriever的实例get()方法

static final String FRAGMENT_TAG = "com.bumptech.glide.manager";
final Map<android.app.FragmentManager, RequestManagerFragment> pendingRequestManagerFragments =
            new HashMap<android.app.FragmentManager, RequestManagerFragment>();
private final Handler handler;
public RequestManager get(Fragment fragment) {
        if (fragment.getActivity() == null) {
            throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
        }
        //不在主线程中
        if (Util.isOnBackgroundThread()) {
          //调用Application类型参数的get()方法
            return get(fragment.getActivity().getApplicationContext());
        } else {
            //管理Fragment的FragmentManager
            FragmentManager fm = fragment.getChildFragmentManager();
            return supportFragmentGet(fragment.getActivity(), fm);
        }
    }
RequestManager supportFragmentGet(Context context, FragmentManager fm) {
       // SupportRequestManagerFragment是一个无UI的Fragment
        SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }
SupportRequestManagerFragment getSupportRequestManagerFragment(final FragmentManager fm) {
        SupportRequestManagerFragment current = (SupportRequestManagerFragment) fm.findFragmentByTag(
            FRAGMENT_TAG);
        if (current == null) {
            current = pendingSupportRequestManagerFragments.get(fm);
            if (current == null) {
                current = new SupportRequestManagerFragment();
                pendingSupportRequestManagerFragments.put(fm, current);
                fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
                handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
            }
        }
        return current;
    }
 public boolean handleMessage(Message message) {
        boolean handled = true;
        Object removed = null;
        Object key = null;
        switch (message.what) {
            case ID_REMOVE_FRAGMENT_MANAGER:
                android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
                key = fm;
                removed = pendingRequestManagerFragments.remove(fm);
                break;
            case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
                FragmentManager supportFm = (FragmentManager) message.obj;
                key = supportFm;
                removed = pendingSupportRequestManagerFragments.remove(supportFm);
                break;
            default:
                handled = false;
        }
        if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
        }
        return handled;
    }
  • SupportRequestManagerFragment:是一个无UI的虚拟的Fragment,它是来辅助Glide来进行生命周期管理的。因为当使用Glide加载图片时,Glide不会感知到Activity的销毁。通过这个虚拟的Fragment来感知到Activity的生命周期,并作出及时的反应。
  • RequestManagerFragment与SupportRequestManagerFragment一样,都是虚拟的Fragment,只不过前者是android.app.Fragment包下的Fragment,后者是v4包下的Fragment。

  分析一下这个过程,在RequestManagerRetriever类的get(Fragment fragment)方法中,先是进行判断,不在主线程中就会调用调用Application类型参数的get()方法,否则生成一个管理Fragment的FragmentManager,然后调用supportFragmentGet()并将生成的FragmentManager对象传入。
  在supportFragmentGet()方法中,先是调用了getSupportRequestManagerFragment()方法;那先进入这个方法中,在这个方法中,先是通过fm.findFragmentByTag( FRAGMENT_TAG)来寻找是否已经存在这个SupportRequestManagerFragment,如果存在就直接返回。否则生成SupportRequestManagerFragment对象,并以FragmentManager为key,SupportRequestManagerFragment对象为value存入pendingRequestManagerFragments中,这个pendingRequestManagerFragments是一个HashMap。接着将刚刚生成的Fragment加入事物管理器中,但是紧接着又调用handel发送了一条消息,我们进入handleMessage()方法中,可以发现它将刚刚加入HashMap的Fragment又删除了。
  怎么回事?刚刚加入进去,怎么紧接着又给删除了。
  来分析一下这个过程。
  首先在Fragment和Activity绑定时,是通过开启事务的方式来进行绑定的,也就是通过Hander来处理的。(感兴趣这个过程的话可以通过看源码来发现)

Glide.with(context).load(url).into(image1);
Glide.with(context).load(url).into(image2);

  我们看上面的两行代码,在同一个Activity中分别为两个ImageView加载图片。
  当第一行代码运行到getSupportRequestManagerFragment()方法时,由于之前没有SupportRequestManagerFragment实例,这个时候会生成一个新的SupportRequestManagerFragment实例,并保存在HashMap中,生成新的SupportRequestManagerFragment实例时,就会发Fragment于Activity的绑定,Handler会发送消息来进行绑定,假设这个消息为m1,紧接着在getSupportRequestManagerFragment()方法中,就会使用Handler来发送从HashMap中删除保存的SupportRequestManagerFragment实例对象的消息,假设这个消息为m2。
  在Handler处理消息时,如果在m1与m2消息之前,Handler的消息队列中还存在其他的消息,此时m1与m2还没有得到处理,就是此时还没有进行Fragment与Activity的绑定。第二行Glide.with(context).load(url).into(image2);代码已经进行到了getSupportRequestManagerFragment()方法了,如果此时我们不将Fragment存入HashMap中,就会重新生成一个SupportRequestManagerFragment,这是Glide所不允许的,每一个Activity或者Fragment在使用Glide时,只能有一个所依附的虚拟的Fragment。所以将之前所生成的SupportRequestManagerFragment存储到HashMap中,这样就不会重复生成SupportRequestManagerFragment,等到SupportRequestManagerFragment与Activity绑定完成后,也就是消息m1处理完成后,再将SupportRequestManagerFragment从HashMap中销毁。
  这个过程分析完了,之后在getSupportRequestManagerFragment()方法中将Fragment返回,接着回到supportFragmentGet()方法中。在这个方法中,接着就生成了RequestManager对象。注意到,在生成这个RequestManager对象时构造器中传入的是刚刚从getSupportRequestManagerFragment()方法中返回的SupportRequestManagerFragment对象中的一些东西。
  Glide的with()过程分析完了,最终得到了Gilde类的with()方法中需要的RequsetManager对象。

Glide的生命周期

  从SupportRequestManagerFragment类开始吧。
  来看一下SupportRequestManagerFragment类。

SupportRequestManagerFragment类

private final ActivityFragmentLifecycle lifecycle;
//在SupportRequestManagerFragment类的构造方法中生成ActivityFragmentLifecycle对象
public SupportRequestManagerFragment() {
        this(new ActivityFragmentLifecycle());
    }
public SupportRequestManagerFragment(ActivityFragmentLifecycle lifecycle) {
        this.lifecycle = lifecycle;
    }
  • ActivityFragmentLifecycle类是生命周期回调的管理类,它实现了LifeCycle接口,会将LifecycleListener的接口加入到ActivityFragmentLifecycle类中的Set集合中,当SupportRequestManagerFragment的生命周期的方法触发时,会调用ActivityFragmentLifeCycle的相应方法。

ActivityFragmentLifeCycle的相应方法

private final Set<LifecycleListener> lifecycleListeners =
            Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
private boolean isStarted;
private boolean isDestroyed;
@Override
    public void addListener(LifecycleListener listener) {
        lifecycleListeners.add(listener);

        if (isDestroyed) {
            listener.onDestroy();
        } else if (isStarted) {
            listener.onStart();
        } else {
            listener.onStop();
        }
    }
void onStart() {
        isStarted = true;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
            lifecycleListener.onStart();
        }
    }

void onStop() {
        isStarted = false;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
            lifecycleListener.onStop();
        }
    }

 void onDestroy() {
        isDestroyed = true;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
            lifecycleListener.onDestroy();
        }
    }

SupportRequestManagerFragment类中

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

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

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

  可以看到当SupportRequestManagerFragment类中的相应的生命周期的方法调用时就会调用ActivityFragmentLifeCycle的相应方法。
  继续SupportRequestManagerFragment类。

SupportRequestManagerFragment类中

private final RequestManagerTreeNode requestManagerTreeNode =
            new SupportFragmentRequestManagerTreeNode();
private final HashSet<SupportRequestManagerFragment> childRequestManagerFragments =
        new HashSet<SupportRequestManagerFragment>();
private SupportRequestManagerFragment rootRequestManagerFragment;
@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        rootRequestManagerFragment = RequestManagerRetriever.get()
                .getSupportRequestManagerFragment(getActivity().getSupportFragmentManager());
        if (rootRequestManagerFragment != this) {
            rootRequestManagerFragment.addChildRequestManagerFragment(this);
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        if (rootRequestManagerFragment != null) {
            rootRequestManagerFragment.removeChildRequestManagerFragment(this);
            rootRequestManagerFragment = null;
        }
    }

 private void addChildRequestManagerFragment(SupportRequestManagerFragment child) {
        childRequestManagerFragments.add(child);
    }

    private void removeChildRequestManagerFragment(SupportRequestManagerFragment child) {
        childRequestManagerFragments.remove(child);
    }

 public Set<SupportRequestManagerFragment> getDescendantRequestManagerFragments() {
        if (rootRequestManagerFragment == null) {
            return Collections.emptySet();
        } else if (rootRequestManagerFragment == this) {
            return Collections.unmodifiableSet(childRequestManagerFragments);
        } else {
            HashSet<SupportRequestManagerFragment> descendants =
                new HashSet<SupportRequestManagerFragment>();
            for (SupportRequestManagerFragment fragment
                : rootRequestManagerFragment.getDescendantRequestManagerFragments()) {
                if (isDescendant(fragment.getParentFragment())) {
                    descendants.add(fragment);
                }
            }
            return Collections.unmodifiableSet(descendants);
        }
    }

private boolean isDescendant(Fragment fragment) {
        Fragment root = this.getParentFragment();
        while (fragment.getParentFragment() != null) {
            if (fragment.getParentFragment() == root) {
                return true;
            }
            fragment = fragment.getParentFragment();
        }
        return false;
    }

private class SupportFragmentRequestManagerTreeNode implements RequestManagerTreeNode {
        @Override
        public Set<RequestManager> getDescendants() {
            Set<SupportRequestManagerFragment> descendantFragments = getDescendantRequestManagerFragments();
            HashSet<RequestManager> descendants = new HashSet<RequestManager>(descendantFragments.size());
            for (SupportRequestManagerFragment fragment : descendantFragments) {
                if (fragment.getRequestManager() != null) {
                    descendants.add(fragment.getRequestManager());
                }
            }
            return descendants;
        }
    }

  在SupportRequestManagerFragment刚刚和Activity建立连接的时候即在onAttach()方法中,会初始化rootRequestManagerFragment实例变量。

  rootRequestManagerFragment = RequestManagerRetriever.get()
                .getSupportRequestManagerFragment(getActivity().getSupportFragmentManager());

  注意这个初始化的过程,在getSupportRequestManagerFragment()方法中传入的是getActivity().getSupportFragmentManager()

  • 如果在Glide.with()时传入的是Activity类型的参数,则会得到Activity的SupportRequestManagerFragment也就是自己。如果在Glide.with()时传入的是Fragment类型的参数,则rootRequestManagerFragment指向的是该Fragment所依赖的Activity的SupportRequestManagerFragment。如果Fragment所依赖的SupportRequestManagerFragment存在则直接调用,否则为该Fragment所依赖的Activity创建SupportRequestManagerFragment。
  • rootRequestManagerFragment指向根Activity的SupportRequestManagerFragment。

  在onAttach()方法中,如果rootRequestManagerFragment不是本身,即rootRequestManagerFragment指向根Activity,则将本身保存到childRequestManagerFragments集合中。也就是在这个集合中保存了Activity的所有的子Fragment的SupportRequestManagerFragment。

  当Fragment销毁时,在这个Fragment中的子Fragment会怎么样?当然也是会销毁啊。也就是父Fragment的生命周期的方法被调用时,子Fragment的生命周期的方法也要会被调用。

  • RequestManagerTreeNode接口:这个接口用来保存请求树节点,SupportFragmentRequestManagerTreeNode类继承于这个接口.
public interface RequestManagerTreeNode {
    /**
     * Returns all descendant {@link RequestManager}s relative to the context of the current {@link RequestManager}.
     */
    Set<RequestManager> getDescendants();
}

  看一下SupportFragmentRequestManagerTreeNode类,这个类只有一个getDescendants()方法,先是利用getDescendantRequestManagerFragments()方法得到一个SupportRequestManagerFragment的集合。
  一个例子,一个Activity有两个Fragment,分别为F1和F2,Activity有一个SRMF(SupportRequestManagerFragment),F1和F2分别有一个SRFM,F1和F2分别又有两个Fragment,分别为F11,F12,F21,F22,这4个Fragment分别拥有SRMF。所以一共有6个SRMF保存在上面所说的rootRequestManagerFragment所指向的集合中。所以当F1生命周期要做出反应时,它的子Fragment分别为F11和F12对应的SRMF也要有相应的反应。但F2的子Fragment的SRMF不做出反应。那怎么得到F1的子Fragment的SRMF,这就是SupportFragmentRequestManagerTreeNode类的作用了。
  接着看。
  在getDescendantRequestManagerFragments()方法中,如果自己不是rootRequestManagerFragment就会在for()循环中遍历返回的rootRequestManagerFragment所指向的集合,这个集合中保存了根Activity的所有的子Fragment的SRMF。接着每遍历一次,就会调用isDescendant()方法进行判断,比如说这个本身的SupportRequestManagerFragment是F1,所有每次都会遍历返回的集合的SPMF是不是F1的子Fragment的SRMF。如果是的话,就将这个SRMF加入集合。
  最后在SupportFragmentRequestManagerTreeNode类getDescendants()方法中得到的都是Fragment的子Fragment的SRMF,最后将子Fragment的SRMF中的RequestManager对象的集合返回。
  所以SupportFragmentRequestManagerTreeNode类getDescendants()方法返回的是Fragment的子Fragment的SRMF的RequestManager对象的集合。

  接着来看RequestManager类

  • RequestManager类实现了LifecycleListener接口。可以启动,停止,管理Glide的Request请求,是实现Glide加载资源的管理类,是Glide生命周期实现的关键类 。

RequestManager类

private final Context context;
private final Lifecycle lifecycle;
private final RequestManagerTreeNode treeNode;
private final RequestTracker requestTracker;
public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {
        this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());
    }

    RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
            RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
        this.context = context.getApplicationContext();
        this.lifecycle = lifecycle;
        this.treeNode = treeNode;
        this.requestTracker = requestTracker;
        ......
        if (Util.isOnBackgroundThread()) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    lifecycle.addListener(RequestManager.this);
                }
            });
        } else {
            lifecycle.addListener(this);
        }
        lifecycle.addListener(connectivityMonitor);
    }

  可以看见,在RequestManager的构造器中将RequestManager对象加入到ActivityLifeCycle中去。
  再看看RequestManager类实现的LifeCycleListener接口的方法。

RequestManager类实现的LifeCycleListener接口的方法(onStop)

public boolean isPaused() {
        Util.assertMainThread();
        return requestTracker.isPaused();
    }
 public void pauseRequests() {
        Util.assertMainThread();
        requestTracker.pauseRequests();
    }
@Override
    public void onStop() {
        pauseRequests();
    }

  可以看见在这些方法中真正起作用的是RequestTracker。

  • RequestTracker类:所有请求的真正执行者

  来捋一下思路,首先是Glide为了管理生命周期,创建了一个无UI的虚拟的Fragment,在这个Fragment创建的时候就生成了ActivityFragmentLifeCycle生命周期的管理的对象,当Fragment的生命周期变化时就会调用ActivityFragmentLifeCycle的相应的方法。而RequestManager类实现了LifeCycleListener接口,在RequestManager的构造器中会将创建的RequestManager对象加入到
ActivityFragmentLifeCycle的管理LifeCycleListener接口的集合中去,所以当ActivityFragmentLifeCycle的相应的方法调用时就会调用RequestManager对象的相应方法,而在RequestManager对象的相应方法真正的执行者是RequestTracker

参考

Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程

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

推荐阅读更多精彩内容