EventBus相關(guān)

看文章前提一句埋泵,重點(diǎn)看代碼里面注釋

一.EventBus是什么谨娜?

EventBus是一款針對(duì)Android優(yōu)化的發(fā)布/訂閱事件總線

二.How to Use?

    //就這幾個(gè)方法,不再贅述攀例,默認(rèn)你用過(guò)
    fun onCreate() {
        EventBus.getDefault().register(this)
    }

    fun onDestory() {
        EventBus.getDefault().unregister(this)
    }

    fun send() {
        EventBus.getDefault().post(DemoEvent())
    }

    @Subscribe
    public fun onReceiveDemoEvent(event: DemoEvent) {
        //balabala 
    }

三.源碼解析(針對(duì)3.1.1版本)

1.EventBus.getDefault().register(Object) 注冊(cè)EventBus

public void register(Object subscriber) {
        //注冊(cè)對(duì)象獲取class
        Class<?> subscriberClass = subscriber.getClass();
        //從訂閱查找器里查找方法
        List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            //遍歷把方法訂閱方法
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

subscriberMethodFinder 對(duì)象從哪里來(lái)羡亩?

先從構(gòu)建說(shuō)起,反手就是一個(gè)建造者模式
public class EventBusBuilder {
    //EventBus的線程池状勤,無(wú)限大鞋怀,可復(fù)用
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

    //布爾值全部為標(biāo)志位,跟你平時(shí)加flag執(zhí)行不同邏輯一樣持搜,不需要特地理解密似,看具體用法
    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;
    boolean eventInheritance = true;
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    //這玩意兒沒(méi)用到,
    List<Class<?>> skipMethodVerificationForClasses;
    //通過(guò)APT注解,在編譯時(shí)就生成對(duì)應(yīng)解析注解為優(yōu)化方式葫盼,這個(gè)默認(rèn)為空残腌,即你找不到
    List<SubscriberInfoIndex> subscriberInfoIndexes;
    //寫(xiě)日志的玩意兒
    Logger logger
    //內(nèi)部就2個(gè)方法,判斷是否為主線程贫导,創(chuàng)建handler(作者給這些handler起名叫poster發(fā)射器)
    MainThreadSupport mainThreadSupport;
    ......
}
    //獲取單例
    public static EventBus getDefault() {
        if (defaultInstance == null) {
            synchronized (EventBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }
    //雖然 public 抛猫,別調(diào)用,沒(méi)啥用
     public EventBus() {
        this(DEFAULT_BUILDER);
    }
      //就是各種賦值孩灯,賦值闺金,
     EventBus(EventBusBuilder builder) {
        logger = builder.getLogger();
        //一些事件集合哈,發(fā)送的事件就是往這里的峰档,說(shuō)到底還是往map里面存
        subscriptionsByEventType = new HashMap<>();
        typesBySubscriber = new HashMap<>();
        stickyEvents = new ConcurrentHashMap<>();
        //3種發(fā)射器败匹,區(qū)別后面講
        mainThreadSupport = builder.getMainThreadSupport();
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
        backgroundPoster = new BackgroundPoster(this);
        asyncPoster = new AsyncPoster(this);
        indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
        //重點(diǎn)看看這個(gè)寨昙,把他拉出來(lái)
        subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
                builder.strictMethodVerification, builder.ignoreGeneratedIndex);
        //后面這些就不講了,就是各種flag的賦值掀亩,然后把線程池給單例
        logSubscriberExceptions = builder.logSubscriberExceptions;
        logNoSubscriberMessages = builder.logNoSubscriberMessages;
        sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
        sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
        throwSubscriberException = builder.throwSubscriberException;
        eventInheritance = builder.eventInheritance;
        executorService = builder.executorService;
    }
    

SubscriberMethodFinder 字面意思舔哪,訂閱方法的查找器
SubscriberMethodFinder(List<SubscriberInfoIndex> subscriberInfoIndexes, boolean strictMethodVerification,boolean ignoreGeneratedIndex)

參數(shù)作用
1.subscriberInfoIndexes 這個(gè)呢其實(shí)就是apt的插件生成的一些EventBusIndex,注入進(jìn)去
2.strictMethodVerification 默認(rèn)值false槽棍,如果為true捉蚤,會(huì)拋異常哈。具體點(diǎn)到這個(gè)類看看就可以
3.ignoreGeneratedIndex 忽略注解炼七,僅通過(guò)反射方式拿取外里,默認(rèn)false哈,就是會(huì)去找index那種

下面看看這個(gè)類里面的方法,回到主題

一開(kāi)始講的這個(gè)EventBus.getDefault().register(XXX)方法里面

   public void register(Object subscriber) {
        Class<?> subscriberClass = subscriber.getClass();
        List<SubscriberMethod> subscriberMethods = 
//看這里這里
subscriberMethodFinder.findSubscriberMethods(subscriberClass);
        synchronized (this) {
            for (SubscriberMethod subscriberMethod : subscriberMethods) {
                subscribe(subscriber, subscriberMethod);
            }
        }
    }

也就是這個(gè)方法 findSubscriberMethods

List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
        //有緩存直接取了哈特石。METHOD_CACHE又是一個(gè)hashMap
        List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
        if (subscriberMethods != null) {
            return subscriberMethods;
        }

        if (ignoreGeneratedIndex) {
            //剛才說(shuō)過(guò)的,開(kāi)了ignoreGeneratedIndex就直接用反射了
            subscriberMethods = findUsingReflection(subscriberClass);
        } else {
            //findUsingInfo 這個(gè)方法是真正根據(jù)要訂閱的類查找訂閱方法了
            subscriberMethods = findUsingInfo(subscriberClass);
        }
        if (subscriberMethods.isEmpty()) {
          //這里提一嘴鳖链,平時(shí)你們寫(xiě)了register但是類里又沒(méi)有Subscribe注解姆蘸,你App就炸了,這里報(bào)的
            throw new EventBusException("Subscriber " + subscriberClass
                    + " and its super classes have no public methods with the @Subscribe annotation");
        } else {
            //查完之后芙委,存?zhèn)€緩存逞敷,常規(guī)操作
            METHOD_CACHE.put(subscriberClass, subscriberMethods);
            return subscriberMethods;
        }
    }

找到findUsingInfo這個(gè)方法

  private List<SubscriberMethod> findUsingInfo(Class<?> subscriberClass) {
        FindState findState = prepareFindState();//準(zhǔn)備一個(gè)查找的state
        findState.initForSubscriber(subscriberClass);//根據(jù)當(dāng)前類初始化 鏈接1
        while (findState.clazz != null) {
            findState.subscriberInfo = getSubscriberInfo(findState);//從subscriberInfoIndexes里面找方法,鏈接2
            if (findState.subscriberInfo != null) {
                //subscriberInfo 這個(gè)里面有方法名什么的灌侣,就是提前已經(jīng)根據(jù)注解解析完了
                SubscriberMethod[] array = findState.subscriberInfo.getSubscriberMethods();
                for (SubscriberMethod subscriberMethod : array) {
                    //檢查添加方法推捐,這里面會(huì)拋出異常,總之不要有同名方法侧啼。沒(méi)問(wèn)題就是add
                    if (findState.checkAdd(subscriberMethod.method, subscriberMethod.eventType)) {
                        findState.subscriberMethods.add(subscriberMethod);
                    }
                }
            } else {
                //沒(méi)找到只好用反射的方式了牛柒。。鏈接3
                findUsingReflectionInSingleClass(findState);
            }
            findState.moveToSuperclass();
        }
        //最后把訂閱好的方法痊乾,返回去皮壁。然后回收f(shuō)indState。就是考慮復(fù)用哪审。蛾魄。
        return getMethodsAndRelease(findState);
    }

    //相關(guān)方法哈.看title找下把
    //鏈接1
    void initForSubscriber(Class<?> subscriberClass) {
            this.subscriberClass = clazz = subscriberClass;
            skipSuperClasses = false;
            subscriberInfo = null;
        }
    
    //鏈接2
    private SubscriberInfo getSubscriberInfo(FindState findState) {
        if (findState.subscriberInfo != null && findState.subscriberInfo.getSuperSubscriberInfo() != null) {
            SubscriberInfo superclassInfo = findState.subscriberInfo.getSuperSubscriberInfo();
            if (findState.clazz == superclassInfo.getSubscriberClass()) {
                return superclassInfo;
            }
        }
        if (subscriberInfoIndexes != null) {
            //這里看到了么。湿滓。眼熟的subscriberInfoIndexes 滴须,就是apt注解提前生成的類里,遍歷去找
            for (SubscriberInfoIndex index : subscriberInfoIndexes) {
                SubscriberInfo info = index.getSubscriberInfo(findState.clazz);
                if (info != null) {
                    return info;
                }
            }
        }
        return null;
    }

//鏈接3 這就是個(gè)反射叽奥。先根據(jù)類扔水,獲取注解,然后解析朝氓。后面一樣的铭污。恋日。也是查找下是不是有,然后添加添加嘹狞。
//2.X版本方式岂膳。。以前人們不是天天說(shuō)磅网,反射谈截,影響效率么,所以現(xiàn)在用原則上用上面那個(gè)效率高涧偷。
 private void findUsingReflectionInSingleClass(FindState findState) {
        Method[] methods;
        try {
            // This is faster than getMethods, especially when subscribers are fat classes like Activities
            methods = findState.clazz.getDeclaredMethods();
        } catch (Throwable th) {
            // Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
            methods = findState.clazz.getMethods();
            findState.skipSuperClasses = true;
        }
        for (Method method : methods) {
            int modifiers = method.getModifiers();
            if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 1) {
                    Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
                    if (subscribeAnnotation != null) {
                        Class<?> eventType = parameterTypes[0];
                        if (findState.checkAdd(method, eventType)) {
                            ThreadMode threadMode = subscribeAnnotation.threadMode();
                            findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
                                    subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
                        }
                    }
                } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                    String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                    throw new EventBusException("@Subscribe method " + methodName +
                            "must have exactly 1 parameter but has " + parameterTypes.length);
                }
            } else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
                String methodName = method.getDeclaringClass().getName() + "." + method.getName();
                throw new EventBusException(methodName +
                        " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
            }
        }
    }

拿到訂閱的方法之后簸喂,要跟對(duì)象綁定起來(lái),在register的方法的遍歷里
subscribe(subscriber, subscriberMethod);
參數(shù)1就是你register的傳進(jìn)來(lái)的對(duì)象燎潮,參數(shù)2是這個(gè)對(duì)象類里面找到的方法

    private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {

        //這里開(kāi)始喻鳄,是先去把方法放到subscriptionsByEventType 這個(gè)事件類型的緩存
        Class<?> eventType = subscriberMethod.eventType;
        Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
        CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions == null) {
            subscriptions = new CopyOnWriteArrayList<>();
            subscriptionsByEventType.put(eventType, subscriptions);
        } else {
            if (subscriptions.contains(newSubscription)) {
                throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
                        + eventType);
            }
        }

        int size = subscriptions.size();
        for (int i = 0; i <= size; i++) {
            if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
                subscriptions.add(i, newSubscription);
                break;
            }
        }
        
        //typesBySubscriber這個(gè)就是isRegister,unRegister使用的哈确封。
        List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
        if (subscribedEvents == null) {
            subscribedEvents = new ArrayList<>();
            typesBySubscriber.put(subscriber, subscribedEvents);
        }
        subscribedEvents.add(eventType);
        
        //以下就是stikyEvent相關(guān)除呵,checkPostStickyEventToSubscription,如果本地有粘性事件
        //注冊(cè)粘性事件的時(shí)候一并取了
        if (subscriberMethod.sticky) {
            if (eventInheritance) {
                Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
                for (Map.Entry<Class<?>, Object> entry : entries) {
                    Class<?> candidateEventType = entry.getKey();
                    if (eventType.isAssignableFrom(candidateEventType)) {
                        Object stickyEvent = entry.getValue();
                        checkPostStickyEventToSubscription(newSubscription, stickyEvent);
                    }
                }
            } else {
                Object stickyEvent = stickyEvents.get(eventType);
                checkPostStickyEventToSubscription(newSubscription, stickyEvent);
            }
        }
    }

斷點(diǎn)看實(shí)際效果爪喘,可以看到通過(guò)subscriberMethodFinder 找到的SubscriberMethod有參數(shù)名颜曾,對(duì)應(yīng)方法,線程模式等等


SubscriberMethod.png

再看 subscriptionsByEventType 緩存的對(duì)象秉剑,就是把事件類型作為key泛豪,前面所拿到的Subscription作為value,進(jìn)行緩存


subscriptionsByEventType.png

最后看typesBySubscriber緩存的對(duì)象侦鹏,就是把object作為key诡曙,該object訂閱對(duì)應(yīng)的事件類型作為value
typesBySubscriber.png

2.EventBus.getDefault().unregister(Object) 解注冊(cè)EventBus

public synchronized void unregister(Object subscriber) {
        //subscribedTypes register的時(shí)候往這個(gè)里面放過(guò),解注冊(cè)的時(shí)候移除
        List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
        if (subscribedTypes != null) {
            for (Class<?> eventType : subscribedTypes) {
                //這個(gè)遍歷的for循環(huán)里面略水,把對(duì)應(yīng)的事件全部移除了噢
                unsubscribeByEventType(subscriber, eventType);
            }
            typesBySubscriber.remove(subscriber);
        } else {
            logger.log(Level.WARNING, "Subscriber ...: " + subscriber.getClass());
        }
    }
 private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
        List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
        if (subscriptions != null) {
            int size = subscriptions.size();
            for (int i = 0; i < size; i++) {
                Subscription subscription = subscriptions.get(i);
                if (subscription.subscriber == subscriber) {
                    subscription.active = false;
                    subscriptions.remove(i);
                    i--;
                    size--;
                }
            }
        }
    }

3.EventBus.getDefault().post(EventObject())發(fā)送事件

最后一步了岗仑,發(fā)送事件

    public void post(Object event) {
        //currentPostingThreadState  這個(gè)是ThreadLocal,可以看作數(shù)據(jù)結(jié)構(gòu)map聚请,key為線程荠雕,value為你設(shè)定的對(duì)象,每個(gè)線程不同驶赏。
        PostingThreadState postingState = currentPostingThreadState.get();
        List<Object> eventQueue = postingState.eventQueue;
        eventQueue.add(event);

        if (!postingState.isPosting) {
            postingState.isMainThread = isMainThread();
            postingState.isPosting = true;
            if (postingState.canceled) {
                throw new EventBusException("Internal error. Abort state was not reset");
            }
            try {
                while (!eventQueue.isEmpty()) {
                    //遍歷發(fā)送事件
                    postSingleEvent(eventQueue.remove(0), postingState);
                }
            } finally {
                postingState.isPosting = false;
                postingState.isMainThread = false;
            }
        }
    }
 private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
        .........
            //回調(diào)這個(gè)方法
        subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
        ........
}

 private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) {
        CopyOnWriteArrayList<Subscription> subscriptions;
        synchronized (this) {
             //從訂閱的方法里炸卑,取出這個(gè)方法
            subscriptions = subscriptionsByEventType.get(eventClass);
        }
        if (subscriptions != null && !subscriptions.isEmpty()) {
            for (Subscription subscription : subscriptions) {
                //取出對(duì)應(yīng)的事件跟subscription
                postingState.event = event;
                postingState.subscription = subscription;
                boolean aborted = false;
                try {
                    //發(fā)送到對(duì)應(yīng)地方去了
                    postToSubscription(subscription, event, postingState.isMainThread);
                    aborted = postingState.canceled;
                } finally {
                    postingState.event = null;
                    postingState.subscription = null;
                    postingState.canceled = false;
                }
                if (aborted) {
                    break;
                }
            }
            return true;
        }
        return false;
    }

POSTING,MAIN,MAIN_ORDERED,這些就是訂閱事件的線程模式

 private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
        switch (subscription.subscriberMethod.threadMode) {
            //默認(rèn)模式
            case POSTING:  
                invokeSubscriber(subscription, event);
                break;
            //主線程
            case MAIN:
                if (isMainThread) {
                    invokeSubscriber(subscription, event);
                } else {
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
            //主線程異步
            case MAIN_ORDERED:
                if (mainThreadPoster != null) {
                    mainThreadPoster.enqueue(subscription, event);
                } else {
                    // temporary: technically not correct as poster not decoupled from subscriber
                    invokeSubscriber(subscription, event);
                }
                break;
            //子線程
            case BACKGROUND:
                if (isMainThread) {
                    backgroundPoster.enqueue(subscription, event);
                } else {
                    invokeSubscriber(subscription, event);
                }
                break;
            //不管在哪個(gè)線程,都異步
            case ASYNC:
                asyncPoster.enqueue(subscription, event);
                break;
            default:
                throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
        }
    }

關(guān)于poster煤傍,其實(shí)就是一開(kāi)始創(chuàng)建的線程池中取出線程來(lái)運(yùn)行盖文,其中比較特殊的是mainThreadPoster,這個(gè)其實(shí)是handler蚯姆,把mainLooper取出來(lái)給他五续,創(chuàng)建出來(lái)的

    Object getAndroidMainLooperOrNull() {
        try {
            return Looper.getMainLooper();
        } catch (RuntimeException e) {
            // Not really a functional Android (e.g. "Stub!" maven dependencies)
            return null;
        }
    }

    class AndroidHandlerMainThreadSupport implements MainThreadSupport {

        private final Looper looper;

        ...

        @Override
        public Poster createPoster(EventBus eventBus) {
            return new HandlerPoster(eventBus, looper, 10);//這里
        }
    }
    //最初的構(gòu)造者模式中洒敏,對(duì)應(yīng)的地方。
    EventBus(EventBusBuilder builder) {
        ......
        mainThreadSupport = builder.getMainThreadSupport();
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
      .....  
    }

最后來(lái)看看invokeSubscriber(Subscription subscription, Object event)

void invokeSubscriber(Subscription subscription, Object event) {
        try {
            //其實(shí)就是調(diào)用method的invoke方法疙驾,其中subscription.subscriber是訂閱對(duì)象凶伙,event是對(duì)應(yīng)發(fā)送的事件
            subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
        } catch (InvocationTargetException e) {
            handleSubscriberException(subscription, event, e.getCause());
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Unexpected exception", e);
        }
    }
至此EventBus整體流程完畢,建議結(jié)合源碼斷點(diǎn)它碎,自己理解下函荣。早在幾年前,就說(shuō)EventBus需要被淘汰扳肛,實(shí)際上現(xiàn)在還有很多公司在用傻挂。看看源碼不吃虧挖息,理解下設(shè)計(jì)理念就好金拒。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市套腹,隨后出現(xiàn)的幾起案子绪抛,更是在濱河造成了極大的恐慌,老刑警劉巖沉迹,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異害驹,居然都是意外死亡鞭呕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)宛官,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)葫松,“玉大人,你說(shuō)我怎么就攤上這事底洗∫该矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵亥揖,是天一觀的道長(zhǎng)珊擂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)费变,這世上最難降的妖魔是什么摧扇? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮挚歧,結(jié)果婚禮上扛稽,老公的妹妹穿的比我還像新娘。我一直安慰自己滑负,他們只是感情好在张,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布用含。 她就那樣靜靜地躺著,像睡著了一般帮匾。 火紅的嫁衣襯著肌膚如雪啄骇。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天辟狈,我揣著相機(jī)與錄音肠缔,去河邊找鬼。 笑死哼转,一個(gè)胖子當(dāng)著我的面吹牛明未,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播壹蔓,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼趟妥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了佣蓉?” 一聲冷哼從身側(cè)響起披摄,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎勇凭,沒(méi)想到半個(gè)月后疚膊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡虾标,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年寓盗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片璧函。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡傀蚌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蘸吓,到底是詐尸還是另有隱情善炫,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布库继,位于F島的核電站箩艺,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宪萄。R本人自食惡果不足惜舅桩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雨膨。 院中可真熱鬧擂涛,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至狰右,卻和暖如春杰捂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棋蚌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工嫁佳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谷暮。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓蒿往,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親湿弦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瓤漏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355