eventbus

先吐槽一下博客園的MarkDown編輯器钥组,推出的時候還很高興博客園支持MarkDown了输硝,試用了下發(fā)現(xiàn)支持不完善就沒用了,這次這篇是在其他編輯器下寫的程梦,復(fù)制過來后發(fā)現(xiàn)点把。橘荠。太爛了。怎么著作為一個技術(shù)博客社區(qū)郎逃,對代碼的支持應(yīng)該完善一下吧哥童,`行內(nèi)代碼塊`不支持就算了,代碼段內(nèi)還不能有空行褒翰,一有空行就識別不了了贮懈。而且試著用MarkDown發(fā)了篇草稿,右邊的側(cè)邊欄竟然被擠到屏幕下方了优训,還影響到了博客布局朵你。。不說了揣非。抡医。簡單修改下標(biāo)題、代碼直接發(fā)表早敬。

概述及基本概念

**EventBus**是一個Android端優(yōu)化的publish/subscribe消息總線忌傻,簡化了應(yīng)用程序內(nèi)各組件間、組件與后臺線程間的通信搁嗓。比如請求網(wǎng)絡(luò),等網(wǎng)絡(luò)返回時通過Handler或Broadcast通知UI箱靴,兩個Fragment之間需要通過Listener通信腺逛,這些需求都可以通過**EventBus**實(shí)現(xiàn)。

作為一個消息總線衡怀,有三個主要的元素:

Event:事件

Subscriber:事件訂閱者棍矛,接收特定的事件

Publisher:事件發(fā)布者,用于通知Subscriber有事件發(fā)生

Event

**Event**可以是任意類型的對象抛杨。

Subscriber

在EventBus中够委,使用約定來指定事件訂閱者以簡化使用。即所有事件訂閱都都是以onEvent開頭的函數(shù)怖现,具體來說茁帽,函數(shù)的名字是onEvent,onEventMainThread屈嗤,onEventBackgroundThread潘拨,onEventAsync這四個,這個和ThreadMode有關(guān)饶号,后面再說铁追。

Publisher

可以在任意線程任意位置發(fā)送事件,直接調(diào)用EventBus的`post(Object)`方法茫船,可以自己實(shí)例化EventBus對象琅束,但一般使用默認(rèn)的單例就好了:`EventBus.getDefault()`扭屁,根據(jù)post函數(shù)參數(shù)的類型,會自動調(diào)用訂閱相應(yīng)類型事件的函數(shù)涩禀。

ThreadMode

前面說了料滥,Subscriber函數(shù)的名字只能是那4個,因?yàn)槊總€事件訂閱函數(shù)都是和一個`ThreadMode`相關(guān)聯(lián)的埋泵,ThreadMode指定了會調(diào)用的函數(shù)幔欧。有以下四個ThreadMode:

PostThread:事件的處理在和事件的發(fā)送在相同的進(jìn)程,所以事件處理時間不應(yīng)太長丽声,不然影響事件的發(fā)送線程礁蔗,而這個線程可能是UI線程。對應(yīng)的函數(shù)名是onEvent雁社。

MainThread: 事件的處理會在UI線程中執(zhí)行浴井。事件處理時間不能太長,這個不用說的霉撵,長了會ANR的磺浙,對應(yīng)的函數(shù)名是onEventMainThread。

BackgroundThread:事件的處理會在一個后臺線程中執(zhí)行徒坡,對應(yīng)的函數(shù)名是onEventBackgroundThread撕氧,雖然名字是BackgroundThread,事件處理是在后臺線程喇完,但事件處理時間還是不應(yīng)該太長伦泥,因?yàn)槿绻l(fā)送事件的線程是后臺線程,會直接執(zhí)行事件锦溪,如果當(dāng)前線程是UI線程不脯,事件會被加到一個隊(duì)列中,由一個線程依次處理這些事件刻诊,如果某個事件處理時間太長防楷,會阻塞后面的事件的派發(fā)或處理。

Async:事件處理會在單獨(dú)的線程中執(zhí)行则涯,主要用于在后臺線程中執(zhí)行耗時操作复局,每個事件會開啟一個線程(有線程池),但最好限制線程的數(shù)目粟判。

根據(jù)事件訂閱都函數(shù)名稱的不同肖揣,會使用不同的ThreadMode,比如果在后臺線程加載了數(shù)據(jù)想在UI線程顯示浮入,訂閱者只需把函數(shù)命名為onEventMainThread龙优。

簡單使用

基本的使用步驟就是如下4步,點(diǎn)擊此鏈接查看例子及介紹。

定義事件類型:

`public class MyEvent {}`

定義事件處理方法:

`public void onEventMainThread`

注冊訂閱者:

`EventBus.getDefault().register(this)`

發(fā)送事件:

`EventBus.getDefault().post(new MyEvent())`

實(shí)現(xiàn)

**EventBus**使用方法很簡單彤断,但用一個東西野舶,如果不了解它的實(shí)現(xiàn)用起來心里總是沒底,萬一出問題咋辦都不知道宰衙,所以還是研究一下它的實(shí)現(xiàn)平道,肯定要Read the fucking Code。其實(shí)主要是`EventBus`這一個類供炼,在看看Code時需要了解幾個概念與成員一屋,了解了這些后實(shí)現(xiàn)就很好理解了。

EventType:onEvent\*函數(shù)中的參數(shù)袋哼,表示事件的類型

Subscriber:訂閱源冀墨,即調(diào)用register注冊的對象,這個對象內(nèi)包含onEvent\*函數(shù)

SubscribMethod:`Subscriber`內(nèi)某一特定的onEvent\*方法涛贯,內(nèi)部成員包含一個`Method`類型的method成員表示這個onEvent\*方法诽嘉,一個`ThreadMode`成員threadMode表示事件的處理線程,一個`Class`類型的eventType成員表示事件的類型`EventType`弟翘。

Subscription虫腋,表示一個訂閱對象,包含訂閱源`Subscriber`稀余,訂閱源中的某一特定方法`SubscribMethod`悦冀,這個訂閱的優(yōu)先級`priopity`

了解了以上幾個概念后就可以看`EventBus`中的幾個重要成員了

//EventType -> List,事件到訂閱對象之間的映射privatefinalMap, CopyOnWriteArrayList>subscriptionsByEventType;//Subscriber -> List睛琳,訂閱源到它訂閱的的所有事件類型的映射privatefinalMap>>typesBySubscriber;//stickEvent事件盒蟆,后面會看到privatefinalMap, Object>stickyEvents;//EventType -> List,事件到它的父事件列表的映射掸掏。即緩存一個類的所有父類privatestaticfinalMap, List>> eventTypesCache =newHashMap, List>>();

注冊事件:Register

通過`EventBus.getDefault().register`方法可以向`EventBus`注冊來訂閱事件茁影,`register`有很多種重載形式宙帝,但大都被標(biāo)記為`Deprecated`了丧凤,所以還是不用為好,前面說了事件處理方法都是以*onEvent*開頭步脓,其實(shí)是可以通過register方法修改的愿待,但相應(yīng)的方法被廢棄了,還是不要用了靴患,就用默認(rèn)的*onEvent*仍侥,除下廢棄的register方法,還有以下4個**public**的`register`方法

publicvoidregister(Object subscriber) {

register(subscriber, defaultMethodName,false, 0);

}publicvoidregister(Object subscriber,intpriority) {

register(subscriber, defaultMethodName,false, priority);

}publicvoidregisterSticky(Object subscriber) {

register(subscriber, defaultMethodName,true, 0);

}publicvoidregisterSticky(Object subscriber,intpriority) {

register(subscriber, defaultMethodName,true, priority);

}

可以看到鸳君,這4個方法都調(diào)用了同一個方法:

privatesynchronizedvoidregister(Object subscriber, String methodName,booleansticky,intpriority) {

List subscriberMethods =subscriberMethodFinder.findSubscriberMethods(subscriber.getClass(),

methodName);for(SubscriberMethod subscriberMethod : subscriberMethods) {

subscribe(subscriber, subscriberMethod, sticky, priority);

}

}

第一個參數(shù)就是訂閱源农渊,第二個參數(shù)就是用到指定方法名約定的,默認(rèn)為*onEvent*開頭或颊,說默認(rèn)是其實(shí)是可以通過參數(shù)修改的砸紊,但前面說了传于,方法已被廢棄,最好不要用醉顽。第三個參數(shù)表示是否是*Sticky Event*沼溜,第4個參數(shù)是優(yōu)先級,這兩個后面再說游添。

在上面這個方法中系草,使用了一個叫`SubscriberMethodFinder`的類,通過其`findSubscriberMethods`方法找到了一個`SubscriberMethod`列表唆涝,前面知道了`SubscriberMethod`表示Subcriber內(nèi)一個onEvent\*方法找都,可以看出來`SubscriberMethodFinder`類的作用是在Subscriber中找到所有以methodName(即默認(rèn)的onEvent)開頭的方法,每個找到的方法被表示為一個`SubscriberMethod`對象石抡。

`SubscriberMethodFinder`就不再分析了檐嚣,但有兩點(diǎn)需要知道:

所有事件處理方法**必需是`public void`類型**的,并且只有一個參數(shù)表示*EventType*啰扛。

`findSubscriberMethods`不只查找*Subscriber*內(nèi)的事件處理方法嚎京,**同時還會查到它的繼承體系中的所有基類中的事件處理方法**。

找到*Subscriber*中的所有事件處理方法后隐解,會對每個找到的方法(表示為`SubscriberMethod`對象)調(diào)用`subscribe`方法注冊鞍帝。`subscribe`方法干了三件事:

根據(jù)`SubscriberMethod`中的*EventType*類型將`Subscribtion`對象存放在`subscriptionsByEventType`中。建立*EventType*到*Subscription*的映射煞茫,每個事件可以有多個訂閱者帕涌。

根據(jù)`Subscriber`將`EventType`存放在`typesBySubscriber`中,建立*Subscriber*到*EventType*的映射续徽,每個Subscriber可以訂閱多個事件蚓曼。

如果是*Sticky*類型的訂閱者,直接向它發(fā)送上個保存的事件(如果有的話)钦扭。

通過*Subscriber*到*EventType*的映射纫版,我們就可以很方便地使一個Subscriber取消接收事件,通過*EventType*到*Sucscribtion*的映射客情,可以方便地將相應(yīng)的事件發(fā)送到它的每一個訂閱者其弊。

Post事件

直接調(diào)用`EventBus.getDefault().post(Event)就可以發(fā)送事件,根據(jù)Event的類型就可以發(fā)送到相應(yīng)事件的訂閱者膀斋。

publicvoidpost(Object event) {

PostingThreadState postingState=currentPostingThreadState.get();

List eventQueue =postingState.eventQueue;

eventQueue.add(event);if(postingState.isPosting) {return;

}else{

postingState.isMainThread= Looper.getMainLooper() ==Looper.myLooper();

postingState.isPosting=true;if(postingState.canceled) {thrownewEventBusException("Internal error. Abort state was not reset");

}try{while(!eventQueue.isEmpty()) {

postSingleEvent(eventQueue.remove(0), postingState);

}

}finally{

postingState.isPosting=false;

postingState.isMainThread=false;

}

}

}

可以看到post內(nèi)使用了`PostingThreadState`的對象梭伐,并且是`ThreadLocal`,來看`PostingThreadState`的定義:

finalstaticclassPostingThreadState {

List eventQueue =newArrayList();booleanisPosting;booleanisMainThread;

Subscription subscription;

Object event;booleancanceled;

}

主要是有個成員`eventQueue`仰担,由于是ThreadLocal糊识,所以結(jié)果就是,每個線程有一個`PostingThreadState`對象,這個對象內(nèi)部有一個事件的隊(duì)列赂苗,并且有一個成員`isPosting`表示現(xiàn)在是否正在派發(fā)事件铃将,當(dāng)發(fā)送事件開始時,會依次取出隊(duì)列中的事件發(fā)送出去哑梳,如果正在派發(fā)事件劲阎,那么post直接把事件加入隊(duì)列后返回,還有個成員`isMainThread`鸠真,這個成員在實(shí)際派發(fā)事件時會用到悯仙,在`postSingleEvent`中會用到。

privatevoidpostSingleEvent(Object event, PostingThreadState postingState)throwsError {

Class eventClass =event.getClass();

List> eventTypes = findEventTypes(eventClass);//1booleansubscriptionFound =false;intcountTypes =eventTypes.size();for(inth = 0; h < countTypes; h++) {//2Class clazz =eventTypes.get(h);

CopyOnWriteArrayListsubscriptions;synchronized(this) {

subscriptions=subscriptionsByEventType.get(clazz);

}if(subscriptions !=null&& !subscriptions.isEmpty()) {//3for(Subscription subscription : subscriptions) {

postingState.event=event;

postingState.subscription=subscription;booleanaborted =false;try{

postToSubscription(subscription, event, postingState.isMainThread);//4aborted =postingState.canceled;

}finally{

postingState.event=null;

postingState.subscription=null;

postingState.canceled=false;

}if(aborted) {break;

}

}

subscriptionFound=true;

}

}if(!subscriptionFound) {

Log.d(TAG,"No subscribers registered for event " +eventClass);if(eventClass != NoSubscriberEvent.class&& eventClass != SubscriberExceptionEvent.class) {

post(newNoSubscriberEvent(this, event));

}

}

}

來看一下`postSingleEvent`這個函數(shù)吠卷,首先看第一點(diǎn)锡垄,調(diào)用了`findEventTypes`這個函數(shù)墨技,代碼不帖了闻坚,這個函數(shù)的應(yīng)用就是,把這個類的類對象徘禁、實(shí)現(xiàn)的接口及父類的類對象存到一個List中返回.

接下來進(jìn)入第二步疾渴,遍歷第一步中得到的List千贯,對List中的每個類對象(即事件類型)執(zhí)行第三步操作,即找到這個事件類型的所有訂閱者向其發(fā)送事件搞坝∩η矗可以看到,**當(dāng)我們Post一個事件時桩撮,這個事件的父事件(事件類的父類的事件)也會被Post敦第,所以如果有個事件訂閱者接收Object類型的事件,那么它就可以接收到所有的事件**店量。

還可以看到芜果,實(shí)際是通過第四步中的`postToSubscription`來發(fā)送事件的,在發(fā)送前把事件及訂閱者存入了`postingState`中融师。再來看`postToSubscription`

privatevoidpostToSubscription(Subscription subscription, Object event,booleanisMainThread) {switch(subscription.subscriberMethod.threadMode) {casePostThread:

invokeSubscriber(subscription, event);break;caseMainThread:if(isMainThread) {

invokeSubscriber(subscription, event);

}else{

mainThreadPoster.enqueue(subscription, event);

}break;caseBackgroundThread:if(isMainThread) {

backgroundPoster.enqueue(subscription, event);

}else{

invokeSubscriber(subscription, event);

}break;caseAsync:

asyncPoster.enqueue(subscription, event);break;default:thrownewIllegalStateException("Unknown thread mode: " +subscription.subscriberMethod.threadMode);

}

}

這里就用到`ThreadMode`了:

如果是PostThread右钾,直接執(zhí)行

如果是MainThread,判斷當(dāng)前線程诬滩,如果本來就是UI線程就直接執(zhí)行霹粥,否則加入`mainThreadPoster`隊(duì)列

如果是后臺線程灭将,如果當(dāng)前是UI線程疼鸟,加入`backgroundPoster`隊(duì)列,否則直接執(zhí)行

如果是Async庙曙,加入`asyncPoster`隊(duì)列

BackgroundPoster

privatefinalPendingPostQueue queue;publicvoidenqueue(Subscription subscription, Object event) {

PendingPost pendingPost=PendingPost.obtainPendingPost(subscription, event);synchronized(this) {

queue.enqueue(pendingPost);if(!executorRunning) {

executorRunning=true;

EventBus.executorService.execute(this);

}

}

}

代碼比較簡單空镜,其實(shí)就是,待發(fā)送的事件被封裝成了`PendingPost`對象,`PendingPostQueue`是一個`PendingPost`對象的隊(duì)列吴攒,當(dāng)`enqueue`時就把這個事件放到隊(duì)列中张抄,`BackgroundPoster`其實(shí)就是一個Runnable對象,當(dāng)`enqueue`時洼怔,如果這個Runnable對象當(dāng)前沒被執(zhí)行署惯,就將`BackgroundPoster`加入EventBus中的一個線程池中,當(dāng)`BackgroundPoster`被執(zhí)行時镣隶,會依次取出隊(duì)列中的事件進(jìn)行派發(fā)极谊。當(dāng)長時間無事件時`BackgroundPoster`所屬的線程被會銷毀,下次再Post事件時再創(chuàng)建新的線程安岂。

HandlerPoster

`mainThreadPoster`是一個`HandlerPoster`對象轻猖,`HandlerPoster`繼承自`Handler`,構(gòu)造函數(shù)中接收一個`Looper`對象域那,當(dāng)向`HandlerPoster` enqueue事件時咙边,會像`BackgroundPoster`一樣把這個事件加入隊(duì)列中, 只是如果當(dāng)前沒在派發(fā)消息就向自身發(fā)送Message

voidenqueue(Subscription subscription, Object event) {

PendingPost pendingPost=PendingPost.obtainPendingPost(subscription, event);synchronized(this) {

queue.enqueue(pendingPost);if(!handlerActive) {

handlerActive=true;if(!sendMessage(obtainMessage())) {thrownewEventBusException("Could not send handler message");

}

}

}

}

在`handleMessage`中會依次取出隊(duì)列中的消息交由`EventBus`直接調(diào)用事件處理函數(shù)次员,而`handleMessage`執(zhí)行所在的線程就是構(gòu)造函數(shù)中傳進(jìn)來的`Looper`所屬的線程败许,在`EventBus`中構(gòu)造`mainThreadPoster`時傳進(jìn)來的是MainLooper,所以會在UI線程中執(zhí)行淑蔚。

AsyncPoster

`AsyncPoster`就簡單了檐束,把每個事件都加入線程池中處理

publicvoidenqueue(Subscription subscription, Object event) {

PendingPost pendingPost=PendingPost.obtainPendingPost(subscription, event);

queue.enqueue(pendingPost);

EventBus.executorService.execute(this);

}

Stick Event

通過`registerSticky`可以注冊Stick事件處理函數(shù),前面我們知道了束倍,無論是`register`還是`registerSticky`最后都會調(diào)用`Subscribe`函數(shù)被丧,在`Subscribe`中有這么一段代碼:

也就是會根據(jù)事件類型從`stickyEvents`中查找是否有對應(yīng)的事件,如果有绪妹,直接發(fā)送這個事件到這個訂閱者甥桂。而這個事件是什么時候存起來的呢,同`register`與`registerSticky`一樣邮旷,和`post`一起的還有一個`postSticky`函數(shù):

if(sticky) {

Object stickyEvent;synchronized(stickyEvents) {

stickyEvent=stickyEvents.get(eventType);

}if(stickyEvent !=null) {//If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)//--> Strange corner case, which we don't take care of here.postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() ==Looper.myLooper());

}

}

當(dāng)通過`postSticky`發(fā)送一個事件時黄选,這個類型的事件的最后一次事件會被緩存起來,當(dāng)有訂閱者通過`registerSticky`注冊時婶肩,會把之前緩存起來的這個事件直接發(fā)送給它办陷。

事件優(yōu)先級Priority

`register`的函數(shù)重載中有一個可以指定訂閱者的優(yōu)先級,我們知道`EventBus`中有一個事件類型到List的映射律歼,在這個映射中民镜,所有的Subscription是按priority排序的,這樣當(dāng)post事件時险毁,優(yōu)先級高的會先得到機(jī)會處理事件制圈。

優(yōu)先級的一個應(yīng)用就事们童,高優(yōu)先級的事件處理函數(shù)可以終于事件的傳遞,通過`cancelEventDelivery`方法鲸鹦,但有一點(diǎn)需要注意慧库,`這個事件的ThreadMode必須是PostThread`,并且只能終于它在處理的事件馋嗜。

# 缺點(diǎn)

無法進(jìn)程間通信齐板,如果一個應(yīng)用內(nèi)有多個進(jìn)程的話就沒辦法了

# 注意事項(xiàng)及要點(diǎn)

同一個onEvent函數(shù)不能被注冊兩次,所以不能在一個類中注冊同時還在父類中注冊

當(dāng)Post一個事件時葛菇,這個事件類的父類的事件也會被Post覆积。

Post的事件無Subscriber處理時會Post `NoSubscriberEvent`事件,當(dāng)調(diào)用Subscriber失敗時會Post `SubscriberExceptionEvent`事件熟呛。

其他

`EventBus`中還有個Util包宽档,主要作用是可以通過`AsyncExecutor`執(zhí)行一個Runnable,通過內(nèi)部的RunnableEx(可以搜索異常的Runnable)當(dāng)Runnable拋出異常時通過`EventBus`發(fā)消息顯示錯誤對話框庵朝。沒太大興趣吗冤,不作分析

項(xiàng)目主頁:https://github.com/greenrobot/EventBus

一個很簡單的Demo,Activity中包含列表和詳情兩個Fragment九府,Activity啟動時加載一個列表椎瘟,點(diǎn)擊列表后更新詳情數(shù)據(jù):EventBusDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市侄旬,隨后出現(xiàn)的幾起案子肺蔚,更是在濱河造成了極大的恐慌,老刑警劉巖儡羔,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宣羊,死亡現(xiàn)場離奇詭異,居然都是意外死亡汰蜘,警方通過查閱死者的電腦和手機(jī)仇冯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來族操,“玉大人苛坚,你說我怎么就攤上這事∩眩” “怎么了泼舱?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長枷莉。 經(jīng)常有香客問我娇昙,道長,這世上最難降的妖魔是什么依沮? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任涯贞,我火速辦了婚禮,結(jié)果婚禮上危喉,老公的妹妹穿的比我還像新娘宋渔。我一直安慰自己,他們只是感情好辜限,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布皇拣。 她就那樣靜靜地躺著,像睡著了一般薄嫡。 火紅的嫁衣襯著肌膚如雪氧急。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天毫深,我揣著相機(jī)與錄音吩坝,去河邊找鬼。 笑死哑蔫,一個胖子當(dāng)著我的面吹牛钉寝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播闸迷,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嵌纲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了腥沽?” 一聲冷哼從身側(cè)響起逮走,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎今阳,沒想到半個月后师溅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盾舌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年险胰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矿筝。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡起便,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窖维,到底是詐尸還是另有隱情榆综,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布铸史,位于F島的核電站鼻疮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏琳轿。R本人自食惡果不足惜判沟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一耿芹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挪哄,春花似錦吧秕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至斯入,卻和暖如春砂碉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刻两。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工增蹭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人磅摹。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓沪铭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親偏瓤。 傳聞我的和親對象是個殘疾皇子杀怠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

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