Rx系列之Rxjava操作符進(jìn)階-使用場(chǎng)景

通過(guò)上一篇《Rx系列之RxJava操作符》,相信已經(jīng)能夠熟練的使用一些基本的操作符了。但是對(duì)于我們大家而言抽米,其實(shí)最傳統(tǒng)的命令式編程已經(jīng)是我們順手就可以拈來(lái)的扶歪,但是理肺,現(xiàn)在用響應(yīng)式編程,突然發(fā)現(xiàn):臥槽善镰,這個(gè)地方用響應(yīng)式怎么寫(xiě)妹萨,這樣寫(xiě)對(duì)么?估計(jì)很多人才開(kāi)始接觸RxJava的時(shí)候應(yīng)該都有這樣的疑慮炫欺。不用擔(dān)心眠副,這一篇就給大家講講RxJava到底該怎么用,在什么情況下用竣稽!

RxJava的使用場(chǎng)景

眼尖的小伙伴囱怕,可能已經(jīng)發(fā)現(xiàn),在上一篇中毫别,很多那么重要的操作符怎么都沒(méi)講娃弓!哈哈哈,答案在這里岛宦。好廢話不多說(shuō)台丛,來(lái)看看Rxjava到底在哪些情況下可以使用。

動(dòng)態(tài)搜索的場(chǎng)景

我們先來(lái)看一個(gè)動(dòng)態(tài)搜索的場(chǎng)景:

搜索

假設(shè),我要在這進(jìn)行網(wǎng)絡(luò)搜索挽霉,那么防嗡,我就要在這里面進(jìn)行網(wǎng)絡(luò)訪問(wèn),如果是輸入完成之后點(diǎn)擊確定進(jìn)行搜索還好侠坎,但是如果是動(dòng)態(tài)收索呢蚁趁?只要搜索框中的搜索內(nèi)容一改變,那么是不是就要進(jìn)行網(wǎng)絡(luò)請(qǐng)求呢实胸?那這樣就不是那么友好了他嫡。為了解決這樣的問(wèn)題,rxjava為我們提供了一個(gè)很好的解決方案:

  • 使用debounce作為textSearch
    debounce()函數(shù)過(guò)濾掉由Observable發(fā)射的速率過(guò)快的數(shù)據(jù)庐完;如果在一個(gè)指定的時(shí)間間隔過(guò)去了仍舊沒(méi)有發(fā)射一個(gè)钢属,那么它將發(fā)射最后的那個(gè)。
    debounce()使用TimeUnit對(duì)象指定時(shí)間間隔门躯。
    是不是感覺(jué)棒棒噠淆党,昂,不管你喜不喜歡讶凉,反正我是愛(ài)死它了宁否。

來(lái)看一下示意圖


debounce示意圖
debounce示意圖

由上圖我們可以看出,在比較密集的數(shù)據(jù)(2缀遍,3慕匠,4,5)發(fā)射之后域醇,其實(shí)最終只是發(fā)射5台谊。

附上代碼:

        RxTextView.textChanges(editText)
                .debounce(5000,TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<CharSequence>() {
                    @Override
                    public void onCompleted() {
                        Log.d(TAG, "onCompleted: onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "onError: onError");
                    }

                    @Override
                    public void onNext(CharSequence charSequence) {
                        Log.d(TAG, "onNext: "+charSequence.toString());
                    }
                });

在這5s內(nèi),我輸入了2譬挚,3锅铅,4,5(出最后一個(gè)5减宣,其他輸入之后就刪除哈)盐须,但是最后得到的結(jié)果卻是:

onNext: 5

注意:這個(gè)操作符會(huì)會(huì)接著最后一項(xiàng)數(shù)據(jù)發(fā)射原始Observable的onCompleted通知,即使這個(gè)通知發(fā)生在你指定的時(shí)間窗口內(nèi)(從最后一項(xiàng)數(shù)據(jù)的發(fā)射算起)漆腌。也就是說(shuō)贼邓,onCompleted通知不會(huì)觸發(fā)限流。

在上面可能會(huì)存在一個(gè)疑問(wèn)闷尿,那就是
RxTextView.textChanges(editText)
這是個(gè)什么東西塑径?你丫怎么沒(méi)講,哈哈填具,這個(gè)呀统舀,要在后面的Rx系列中單獨(dú)來(lái)講,所以不要著急,暫時(shí)說(shuō)一下這個(gè)的功能誉简,這個(gè)RxTextView.textChanges(editText)其實(shí)是RxBinding里面的一個(gè)對(duì)控件的操作碉就,其功能就跟TextWatcher一樣,就是對(duì)數(shù)據(jù)的變更進(jìn)行監(jiān)聽(tīng)闷串,所以上面的數(shù)據(jù)變化之后5s后將數(shù)據(jù)發(fā)射出去瓮钥。嗯嗯,到這里就把動(dòng)態(tài)搜索場(chǎng)景講解了窿克。

緩存檢測(cè)場(chǎng)景

在請(qǐng)求取數(shù)據(jù)的處理過(guò)程中骏庸,我們的操作一般是這樣一個(gè)原理:

  • ** 首先檢查內(nèi)存是否有緩存**
  • 然后檢查文件緩存中是否有
  • 最后才從網(wǎng)絡(luò)中取
    任何一步一旦發(fā)現(xiàn)數(shù)據(jù)后面的操作都不執(zhí)行
    在rxjava中為我們提供了兩個(gè)解決這個(gè)問(wèn)題的操作符毛甲,分別是: concatfirst

concat
不交錯(cuò)的發(fā)射兩個(gè)或多個(gè)Observable
concat操作符連接多個(gè)Observable的輸出年叮,就好像它們是一個(gè)Observable,第一個(gè)Observable發(fā)射的所有數(shù)據(jù)在第二個(gè)Observable發(fā)射的任何數(shù)據(jù)前面玻募,以此類(lèi)推只损。直到前面一個(gè)Observable終止,Concat
才會(huì)訂閱額外的一個(gè)Observable

請(qǐng)注意上面所說(shuō)的“就好像它們是一個(gè)Observable”七咧,其實(shí)并不是一個(gè)Observable跃惫,是前面一個(gè)停止之后才會(huì)訂閱下一個(gè),所以說(shuō)他們并不是一個(gè)艾栋,請(qǐng)君注意咯爆存。

concat示意圖
concat示意圖

如上所示,就是將兩個(gè)Observable連接起來(lái)了蝗砾。
還有一個(gè)實(shí)例方法concatWith先较,它是和concat等價(jià)的:Observable.concat(a,b)==a.concatWith(b)

來(lái)看一下是不是這個(gè)樣子的:

        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted: onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError: onError");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG, "onNext: " + integer);
            }
        };

        Observable a = Observable.just(1, 2, 3, 4, 5);
        Observable b = Observable.just(6, 7, 8, 9, 10);

        Observable.concat(a, b)
                .subscribe(subscriber);

然后我們得到:

onNext: 1
 ...
onNext: 10
onCompleted: onCompleted

這時(shí)估計(jì)就會(huì)有人說(shuō)了:你不是說(shuō)這個(gè)操作符其實(shí)是將兩個(gè)訂閱連接起來(lái)了嘛!那么悼粮,為什么只是在最后打印了onCompleted闲勺,在onNext: 5后面不是也應(yīng)該打印一個(gè)嗎?
我們都知道觀察者和被觀察者之間扣猫,是由訂閱建立關(guān)系的菜循,那么對(duì)于被觀察者來(lái)說(shuō),確實(shí)我發(fā)射了兩個(gè)數(shù)據(jù)源申尤,但是對(duì)于觀察者來(lái)說(shuō)癌幕,我不知道你有幾個(gè)數(shù)據(jù)源,我的職責(zé)就只是昧穿,數(shù)據(jù)發(fā)射過(guò)來(lái)后序芦,我打印而已。所以粤咪,只有當(dāng)onNext沒(méi)有接收到數(shù)據(jù)時(shí)谚中,才會(huì)調(diào)用onCompleted

最后對(duì)這個(gè)操作符,再補(bǔ)充一點(diǎn):如果當(dāng)?shù)谝粋€(gè)Observable a拋異常宪塔,那么將不會(huì)繼續(xù)執(zhí)行后面的Observable b了磁奖。
如果想測(cè)試請(qǐng)將上面的

Observable a = Observable.just(1, 2, 3, 4, 5);

變成

Observable a = Observable.just(1, 2, 3, 4, new RuntimeException());

進(jìn)行測(cè)試。

first
只發(fā)射第一項(xiàng)(或者滿(mǎn)足某個(gè)條件的第一項(xiàng))數(shù)據(jù)

first示意圖
first示意圖

由上圖我們可以看出某筐,這個(gè)只要第一項(xiàng)滿(mǎn)足條件比搭,后面的將不會(huì)再進(jìn)行發(fā)射,所以只是得到了1這個(gè)數(shù)字南誊。

        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted: onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError: onError");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG, "onNext: " + integer);
            }
        };

        Observable a = Observable.just(1, 2, 3, 4, 5);
        a.first().subscribe(subscriber);

得到結(jié)果:

onNext: 1
onCompleted: onCompleted

這個(gè)應(yīng)該很容易就看出來(lái)了身诺。就是只是打印了第一個(gè)數(shù)據(jù)!
在這兒必須為大家區(qū)別一個(gè)操作符:single()抄囚,這個(gè)操作符也是只打印一個(gè)數(shù)據(jù)的霉赡,但是single()和first()最大的區(qū)別在于:前者只會(huì)發(fā)射一個(gè)數(shù)據(jù),不能發(fā)射多個(gè)幔托,否則會(huì)報(bào)錯(cuò)穴亏;而first確實(shí)滿(mǎn)足條件的那一個(gè)。
如下:

    Observable a = Observable.just(1);
    a.single().subscribe(subscriber);

估計(jì)到這兒應(yīng)該已經(jīng)有人知道了上面的3個(gè)步驟改真沒(méi)寫(xiě)了重挑,來(lái)我們來(lái)看看代碼:

 final Observable<String> memory = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                if (memoryCache != null) {
                    subscriber.onNext(memoryCache);
                } else {
                    subscriber.onCompleted();
                }
            }
        });
        Observable<String> disk = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                String cachePref = rxPreferences.getString("cache").get();
                if (!TextUtils.isEmpty(cachePref)) {
                    subscriber.onNext(cachePref);
                } else {
                    subscriber.onCompleted();
                }
            }
        });

        Observable<String> network = Observable.just("network");

        //依次檢查memory嗓化、disk、network  
        Observable
                .concat(memory, disk, network)
                .first()
                .subscribeOn(Schedulers.newThread())
                .subscribe(s -> {
                    memoryCache = "memory";
                    System.out.println("--------------subscribe: " + s);
                });

現(xiàn)在看上面的代碼是不是就知道它在干什么了谬哀,是不是很簡(jiǎn)單!這個(gè)緩存檢測(cè)場(chǎng)景就講到這里刺覆。

輸入合法場(chǎng)景

在某些時(shí)候,我們需要所以的輸入都合法后史煎,我們的某些按鈕才亮起來(lái)谦屑,或者才能點(diǎn)擊,如下圖:


輸入合法示意圖

在這個(gè)場(chǎng)景中劲室,我們得掌握兩個(gè)操作符:skipcombineLatest

skip
抑制Observable發(fā)射的前N項(xiàng)數(shù)據(jù)

skip示意圖
skip示意圖

從上圖可以看到伦仍,總共發(fā)射了4個(gè)數(shù)據(jù),只有最后兩個(gè)發(fā)射出去了很洋,這就是skip(2)的作用充蓝。

        Observable.just(1,2,3,4).skip(2).subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted: onCompleted");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError: onError");
            }

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG, "onNext: "+integer);
            }
        });

得到如下結(jié)果:

onNext: 3
onNext: 4
onCompleted: onCompleted

combineLatest
當(dāng)多個(gè)Observables中的任何一個(gè)發(fā)射了數(shù)據(jù)時(shí),使用一個(gè)函數(shù)結(jié)合每個(gè)Observable發(fā)射的最近數(shù)據(jù)項(xiàng)喉磁,并且基于這個(gè)函數(shù)的結(jié)果發(fā)射數(shù)據(jù)谓苟。
CombineLatest在原始的Observable中任意一個(gè)發(fā)射了數(shù)據(jù)時(shí)發(fā)射一條數(shù)據(jù)。當(dāng)原始Observables的任何一個(gè)發(fā)射了一條數(shù)據(jù)時(shí)协怒,CombineLatest
使用一個(gè)函數(shù)結(jié)合它們最近發(fā)射的數(shù)據(jù)涝焙,然后發(fā)射這個(gè)函數(shù)的返回值。
一開(kāi)始看到這句話孕暇,我又懵b了仑撞,這tm幾個(gè)意思赤兴?我們先來(lái)看看這個(gè)場(chǎng)景的實(shí)現(xiàn)代碼,然后再解釋?zhuān)?/p>

        private void combineLatestEvent() {

        Observable<CharSequence> usernameObservable = RxTextView.textChanges(mUsername).skip(1);
        Observable<CharSequence> emailObservable = RxTextView.textChanges(mEmail).skip(1);
        Observable<CharSequence> passwordObservable = RxTextView.textChanges(mPassword).skip(1);

       Subscription subscription = Observable.combineLatest(usernameObservable, emailObservable,
                passwordObservable,
                new Func3<CharSequence, CharSequence, CharSequence, Boolean>() {
                    @Override
                    public Boolean call(CharSequence userName, CharSequence email, CharSequence
                            password) {

                        boolean isUserNameValid = !TextUtils.isEmpty(userName) && (userName
                                .toString().length() > 2 && userName.toString().length() < 9);

                        if (!isUserNameValid) {
                            mUsername.setError("用戶(hù)名無(wú)效");
                        }


                        boolean isEmailValid = !TextUtils.isEmpty(email) && Patterns
                                .EMAIL_ADDRESS.matcher(email).matches();

                        if (!isEmailValid) {
                            mEmail.setError("郵箱無(wú)效");
                        }

                        boolean isPasswordValid = !TextUtils.isEmpty(password) && (password
                                .toString().length() >5 && password.toString().length() < 11);

                        if (!isPasswordValid) {
                            mPassword.setError("密碼無(wú)效");
                        }


                        return isUserNameValid && isEmailValid && isPasswordValid;
                    }
                })
                .subscribe(getObserver());
    }

  
    private Observer<Boolean> getObserver() {
        return new Observer<Boolean>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Boolean aBoolean) {
                //更改注冊(cè)按鈕是否可用的狀態(tài)
                register.setEnabled(aBoolean);
            }
        };
    }

這個(gè)場(chǎng)景桶良,有3個(gè)edittext沮翔,分別是mUsername采蚀,mEmail榆鼠,mPassword璧眠,通過(guò)輸入合法的內(nèi)容進(jìn)行判定注冊(cè)按鈕是否亮起來(lái)责静。
當(dāng)我點(diǎn)擊其中的任何一個(gè)進(jìn)行編寫(xiě)的時(shí)候灾螃,就會(huì)發(fā)射數(shù)據(jù)腰鬼,發(fā)射的是什么熄赡?是我們編輯的內(nèi)容嗎彼硫?其實(shí)不是的拧篮,發(fā)射的是結(jié)合Func3這個(gè)方法的返回值串绩,在這里這個(gè)返回值是Boolean型的礁凡。返回了boolean型之后顷牌,就可以在觀察者里面設(shè)置注冊(cè)按鈕是否亮起來(lái)∪脱冢現(xiàn)在再看上面那句高深莫測(cè)的話疗锐,是不是簡(jiǎn)單多了滑臊!

這兒可能有人有疑問(wèn)了:這3個(gè)edittext為什么要使用skip(1)呢雇卷?
答案其實(shí)很簡(jiǎn)答啊关划,那就是當(dāng)我們不寫(xiě)skip(1)的時(shí)候裤翩,edittext中沒(méi)有輸入任何值的時(shí)候调榄,會(huì)把它當(dāng)作第一個(gè)數(shù)據(jù)進(jìn)行發(fā)射每庆,雖然發(fā)射的是個(gè)空數(shù)據(jù)缤灵,但是還是會(huì)發(fā)射啊!
奧偶凤价,這個(gè)場(chǎng)景解釋完了利诺!

數(shù)據(jù)過(guò)期場(chǎng)景

其實(shí)這個(gè)場(chǎng)景可以和上面的數(shù)據(jù)緩存檢測(cè)場(chǎng)景進(jìn)行合并:在緩存檢測(cè)場(chǎng)景中慢逾,我們知道,如果memory中沒(méi)有數(shù)據(jù)变擒,就從disk上面尋找娇斑,然后再是網(wǎng)絡(luò)請(qǐng)求,那么苦丁,問(wèn)題來(lái)了旺拉,如果我們的memory中一直有數(shù)據(jù)蛾狗,但是網(wǎng)絡(luò)數(shù)據(jù)已經(jīng)變更了姻僧,又由于緩存檢測(cè)原則的只要有一個(gè)有數(shù)據(jù)就不會(huì)進(jìn)行網(wǎng)絡(luò)請(qǐng)求了撇贺,這就會(huì)造成我們顯示的數(shù)據(jù)一直是一個(gè)舊數(shù)據(jù)松嘶。

哦豁

那這個(gè)該怎么辦呢巢音?
解決方法有如下兩個(gè):

  • 采用定時(shí)進(jìn)行清除本地緩存數(shù)據(jù)
  • 采用過(guò)濾操作符

我們先來(lái)看看第一種官撼,如果是進(jìn)行定時(shí)做本地?cái)?shù)據(jù)清空的話掠哥,那么就會(huì)用到续搀,我們一個(gè)輪詢(xún)的操作符Interval
創(chuàng)建一個(gè)按固定時(shí)間間隔發(fā)射整數(shù)序列的Observable
Interval通俗的講禁舷,就是每隔一段時(shí)間過(guò)后做什么事情!上一篇已經(jīng)講過(guò)了霜大,所以這里就不詳細(xì)講解了战坤,直接上代碼:

        Observable.interval(3, TimeUnit.SECONDS).subscribe(new Observer<Long>() {
           ...
           @Override
           public void onNext(Long aLong) {
                //清除緩存操作
           }
       });

很多人可能會(huì)想到,那既然囊卜,我能夠用清除本地緩存的方法,那么能不能用玉掸,每隔一段時(shí)間進(jìn)行請(qǐng)求司浪,讓請(qǐng)求的結(jié)果與本地緩存進(jìn)行合并呢?
答案是肯定的租谈,來(lái)看如下代碼:

    Observable.create(new Observable.OnSubscribe<String>() {  
            @Override  
           public void call(final Subscriber<? super String> observer) {  
 
              Schedulers.newThread().createWorker()  
                    .schedulePeriodically(new Action0() {  
                          @Override  
                          public void call() {  
                              observer.onNext(doNetworkCallAndGetStringResult());  
                         }  
                      }, INITIAL_DELAY, POLLING_INTERVAL, TimeUnit.MILLISECONDS);  
            }  
        }).subscribe(new Action1<String>() {  
           @Override  
           public void call(String s) {  
               
           }  
      })  

這個(gè)就是使用schedulePeriodically做輪詢(xún)請(qǐng)求

這樣造成每過(guò)一定時(shí)間我們就會(huì),清除緩存或者網(wǎng)絡(luò)請(qǐng)求间校。讀到這兒,是不是感覺(jué)這個(gè)方法真爛滓彰,哈哈哈郎哭,不著急夸研,我們不是還有第二種方法嘛!來(lái)接著看第二種方法

  • 采用過(guò)濾操作符
    其實(shí)這個(gè)操作符我們已經(jīng)講過(guò)了絮供,那就是操作符first,回顧一下上面的代碼袍榆,就是我們的first就是保證宿崭,眾多的數(shù)據(jù),有一個(gè)符合條件就發(fā)射數(shù)據(jù)吆鹤,后面的都將不執(zhí)行梗醇。我們的是否需要更新的條件不加在這里温鸽,就沒(méi)天理咯!
Observable source = Observable
    .concat(memory, disk, network)
    .first(new Func1() {
      @Override public Boolean call(Data data) {
        return data.isUpToDate();
      }
    });

哇偶手负,這個(gè)操作符完美的解決了如上的問(wèn)題嗤朴!那你丫的還將那么多,呵呵虫溜,我只是給大家講解操作符的使用場(chǎng)景而已雹姊,那個(gè)適合哪個(gè)場(chǎng)景,取決你們自己咯衡楞!

這一篇主要講解的內(nèi)容的就到這兒了吱雏,下面還有一些其他的場(chǎng)景,就簡(jiǎn)單的介紹一下瘾境。

其他的場(chǎng)景

合并兩個(gè)數(shù)據(jù)源場(chǎng)景

使用merge合并兩個(gè)數(shù)據(jù)源歧杏,代碼如下:

    Observable.merge(getInfoFromFile(), getInfoFromNet())  
           .observeOn(AndroidSchedulers.mainThread())  
              .subscribe(new Subscriber<String>() {  
                  @Override  
                  public void onCompleted() {  
                     Log.d(TAG, "onCompleted: onCompleted");
                 }  
 
                 @Override  
                  public void onError(Throwable e) {  
                    Log.d(TAG, "onError: onError");
                  }  
  
                  @Override  
                  public void onNext(String data) {  
                       Log.d(TAG, "onNext: only one ! ");
             });  

Retrofit結(jié)合RxJava場(chǎng)景

這個(gè)場(chǎng)景的話,大家可以查看扔物線大神寫(xiě)的給 Android 開(kāi)發(fā)者的 RxJava 詳解迷守,其中講解到了這個(gè)場(chǎng)景的結(jié)合犬绒!

就操作符使用場(chǎng)景這一塊而言,大概就講解這么多兑凿,如果大家有其他的使用場(chǎng)景凯力,我們可以一起交流哦。感謝大家的支持礼华,謝謝咐鹤!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市圣絮,隨后出現(xiàn)的幾起案子祈惶,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捧请,死亡現(xiàn)場(chǎng)離奇詭異凡涩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)疹蛉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)活箕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人氧吐,你說(shuō)我怎么就攤上這事讹蘑。” “怎么了筑舅?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵座慰,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我翠拣,道長(zhǎng)版仔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任误墓,我火速辦了婚禮蛮粮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谜慌。我一直安慰自己然想,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布欣范。 她就那樣靜靜地躺著变泄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恼琼。 梳的紋絲不亂的頭發(fā)上妨蛹,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音晴竞,去河邊找鬼蛙卤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛噩死,可吹牛的內(nèi)容都是我干的颤难。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼甜滨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼乐严!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起衣摩,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后艾扮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體既琴,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年泡嘴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了甫恩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酌予,死狀恐怖磺箕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抛虫,我是刑警寧澤松靡,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站建椰,受9級(jí)特大地震影響雕欺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棉姐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一屠列、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伞矩,春花似錦笛洛、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至侥袜,卻和暖如春蝌诡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枫吧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工浦旱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人九杂。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓颁湖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親例隆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子甥捺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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