android 初識(shí)EventBus

title: android 初識(shí)EventBus
date: 2016-04-17
tags: eventbus


本文檔基于EventBus 3.0.0

EventBus是一個(gè)發(fā)布/訂閱事件總線,用來(lái)優(yōu)化android程序锅知。

EventBus-Publish-Subscribe.png

EventBus是什么

  • 簡(jiǎn)化組件之間通信砸烦。
  1. 解耦事件的發(fā)送者和接受者。
  2. 在Activities,F(xiàn)ragments和后臺(tái)線程之間表現(xiàn)的很好
  3. 避免復(fù)雜的和容易出錯(cuò)的依賴和生命周期
  • 使代碼簡(jiǎn)單
  • 快雳灵,高性能:特別是在注重性能的Android上。也許在其同類的解決方案是最快的闸盔。
  • 忻跽蕖(jar包小于50K),但是強(qiáng)大:EventBus是一個(gè)很小的庫(kù)迎吵,它的API超級(jí)簡(jiǎn)單躲撰。但是你的軟件架構(gòu)會(huì)非常受益于組件解耦:當(dāng)使用事件的時(shí)候,訂閱者不需要知道發(fā)送者是誰(shuí)击费。
  • 在實(shí)踐中被100,000,000+的應(yīng)用安裝測(cè)試拢蛋。
  • 有在線程間傳遞,訂閱優(yōu)先級(jí)等高級(jí)特性
  • 基于方便的注解(不犧牲性能):只需要通過(guò)在你的訂閱方法放置@Subscribe注解蔫巩。因?yàn)槭窃诰幾g的時(shí)候索引注解谆棱,EventBus不需要在app運(yùn)行時(shí)間做注解反射(在android上會(huì)很慢)快压。
  • android主線程傳遞:當(dāng)和UI交互的時(shí)候,無(wú)論這個(gè)事件是怎么提交的垃瞧,EventBus都可以在主線程傳遞事件蔫劣。
  • 后臺(tái)線程傳遞:如果訂閱者運(yùn)行長(zhǎng)時(shí)間的任務(wù),EventBus也可以使用后臺(tái)線程來(lái)避免UI阻塞个从。
  • 事件和訂閱繼承:在EventBus中脉幢,事件和訂閱類都是面向?qū)ο蟮姆独J录嗀是B的父類嗦锐。提交B類型的事件也會(huì)提交給對(duì)A感興趣的訂閱者嫌松。類似的訂閱者類也是如此。
  • 0配置:在代碼中任何位置可以立刻使用一個(gè)默認(rèn)的EventBus實(shí)例意推。
  • 可配置:可以按需求調(diào)整EventBus豆瘫,可以使用建造者模式調(diào)整行為。
  • EventBus和Android的廣播和Intent系統(tǒng)有什么不同
    不像Android的廣播和intent系統(tǒng)菊值,EventBus使用標(biāo)準(zhǔn)的java類作為事件并且提供更多的方便的API外驱。EventBus更多的使用場(chǎng)景是不想設(shè)置麻煩的intent,設(shè)置intent extras腻窒,實(shí)現(xiàn)廣播接收者昵宇,再提取intent extras。而且開銷更低儿子。

添加到你的工程
EventBus可以從JCenter和Maven中央倉(cāng)庫(kù)獲取瓦哎,所以只需在gradle腳本中添加這個(gè)依賴:

complie 'org.greenrobot:eventbus:3.0.0'

開始使用EventBus

使用EventBus只需3步。在此之前先在Gradle腳本中添加依賴柔逼。

complie 'org.greenrobot:eventbus:3.0.0'

第一步:定義事件
事件是POJO(plain old java object)類型,不需要什么特別的需求

public class MessageEvent {
    public final String message;
    public MessageEvent(String message) {
        this.message = message;
    }
}

第二步:準(zhǔn)備訂閱者
訂閱者實(shí)現(xiàn)事件處理方法(也叫做訂閱者方法)蒋譬,這個(gè)方法會(huì)在事件提交的時(shí)候被調(diào)用。這些是使用@Subscribe注解定義的愉适。請(qǐng)注意EventBus 3的方法名字可以自由選擇(不像EventBus 2中約束的那樣)犯助。

// 當(dāng)一個(gè)Message Event提交的時(shí)候這個(gè)方法會(huì)被調(diào)用
@Subscribe
public void onMessageEvent(MessageEvent event){
    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}

// 當(dāng)一個(gè)SomeOtherEvent被提交的時(shí)候這個(gè)方法被調(diào)用。
@Subscribe
public void handleSomethingElse(SomeOtherEvent event){
    doSomethingWith(event);
}

訂閱者也需要在bus中注冊(cè)和注銷维咸。只有在訂閱者注冊(cè)的時(shí)候剂买,他們才會(huì)收到事件。在Android中癌蓖,Activities和Fragments通常綁定他們的生命周期.

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
   EventBus.getDefault().unregister(this);
    super.onStop();
}

第三步:提交事件
在代碼中任意位置提交事件瞬哼。所有當(dāng)前注冊(cè)的匹配事件類型的訂閱者都會(huì)收到事件。

EventBus.getDefault().post(new MessageEvent("Hello everyone!"));

線程間傳遞(線程模式)

事件可以在不同線程間傳遞租副。典型的使用就是用來(lái)處理UI改變坐慰,網(wǎng)絡(luò)操作,或者耗時(shí)的操作用僧。EventBus可以處理這些任務(wù)并同步UI線程(不必再考慮線程轉(zhuǎn)換结胀,使用AsyncTask两残,等)。
有四種線程模式:
線程模式:POSTING
默認(rèn)情況下把跨,訂閱者在被提交事件的線程被調(diào)用人弓。事件同步完成傳遞,一旦事件提交所有的訂閱者都會(huì)被調(diào)用着逐。因?yàn)楸苊饬司€程切換崔赌,這種模式意味著開銷最小。所以對(duì)那些花費(fèi)很短的時(shí)間來(lái)完成耸别,不需要在主線程中的簡(jiǎn)單的任務(wù)健芭,推薦使用這種模式。事件處理程序使用這種模式應(yīng)該是很快能返回的秀姐,避免阻塞提交線程比如主線程慈迈。比如:

@Subscribe(threadMode = ThreadMode.POSTING) // ThreadMode is optional here
public void onMessage(MessageEvent event) {
    log(event.message);
}

線程模式:MAIN
訂閱者會(huì)在主線程被調(diào)用。如果提交的線程是主線程省有,事件處理方法會(huì)直接被調(diào)用(就像Thread.POSTING描述的那樣同步)痒留。事件處理程序使用這個(gè)模式必須能夠快速返回避免阻塞主線程。比如:

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(MessageEvent event) {
    textField.setText(event.message);
}

線程模式:BACKGROUND
訂閱者會(huì)在后臺(tái)線程被調(diào)用蠢沿。如果不是在主線程提交伸头,事件處理方法會(huì)直接在提交線程被調(diào)用。如果是在主線程提交舷蟀,EventBus使用一個(gè)單獨(dú)的后臺(tái)線程按順序傳遞所有事件恤磷。事件處理使用這種模式應(yīng)該能夠盡快返回避免阻塞后臺(tái)線程。

@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessage(MessageEvent event){
    saveToDisk(event.message);
}

線程模式:ASYNC
事件處理方法會(huì)在一個(gè)單獨(dú)的線程被調(diào)用野宜。這個(gè)線程通常和提交的線程和主線程是獨(dú)立的扫步。提交的事件從不等待事件處理方法。事件處理方法如果需要花費(fèi)一段時(shí)間比如訪問(wèn)網(wǎng)絡(luò)應(yīng)該使用這種模式匈子。避免在同一時(shí)間觸發(fā)大量長(zhǎng)時(shí)間異步的處理方法來(lái)限制并發(fā)的線程河胎。EventBus使用一個(gè)線程池來(lái)有效重復(fù)利用線程完成的異步事件處理程序的通知。

@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessage(MessageEvent event){
    backend.send(event.message);
}

配置

EventBusBuilder用來(lái)配置EventBus旬牲。比如仿粹,如果一個(gè)提交的事件沒(méi)有訂閱者搁吓,可以使EventBus保持安靜原茅。

EventBus eventBus = EventBus.builder().logNoSubscriberMessages(false)
    .sendNoSubscriberEvent(false).build();

另一個(gè)例子是當(dāng)一個(gè)訂閱者拋出一個(gè)異常的失敗。注意:默認(rèn)情況下堕仔,EventBus捕獲異常從onEvent方法中拋出并且發(fā)出一個(gè)SubscriberExceptionEvent 擂橘,這個(gè)事件可以不必處理。

EventBus eventBus = EventBus.builder().throwSubscriberException(true).build();

更多配置摩骨,查看官方文檔
配置默認(rèn)EventBus實(shí)例
使用EventBus.getDefault()是一種簡(jiǎn)單的方法來(lái)獲取共享的EventBus實(shí)例通贞。EventBusBuilder也可以使用installDefaultEventBus()方法來(lái)配置這個(gè)默認(rèn)的實(shí)例朗若。
比如,當(dāng)在onEvent方法中發(fā)生異常的時(shí)候昌罩,可以配置默認(rèn)的EventBus實(shí)例來(lái)重新拋出異常哭懈。建議在使用DEBUG模式的時(shí)候這么使用,因?yàn)檫@樣app會(huì)因?yàn)檫@個(gè)異常而崩潰茎用。

EventBus.builder().throwSubscriberException(BuildConfig.DEBUG).installDefaultEventBus();

注意:只有在默認(rèn)EventBus實(shí)例在第一次使用之前這么配置一次遣总。后續(xù)調(diào)用installDefaultEventBus() 會(huì)拋出異常。這確保應(yīng)用程序的行為一致轨功⌒癯猓可以在Application類中配置默認(rèn)的EventBus。

Sticky Event

一些事件攜帶在事件提交之后仍然感興趣的信息古涧。比如垂券,一個(gè)事件標(biāo)記一些初始化完成或者一些傳感器或位置數(shù)據(jù)的最新的值∠刍可以使用sticky事件來(lái)代替你自己的實(shí)現(xiàn)菇爪。EventBus在內(nèi)存中保持某一個(gè)類型的最后的sticky事件。這個(gè)sticky事件可以傳遞到訂閱者或者也可以被明確的查詢柒昏。因此娄帖,不需要任何特殊的邏輯來(lái)考慮已經(jīng)可用的數(shù)據(jù)。
Sticky實(shí)例
一個(gè)sticky事件是一段時(shí)間之前被提交的昙楚。

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));

現(xiàn)在近速,sticky事件被提交了,一個(gè)新的activity啟動(dòng)堪旧。在注冊(cè)過(guò)程中所有的sticky的訂閱者方法都會(huì)立刻獲取到之前提交的sticky事件:

@Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
    public void onEvent(MessageEvent event) {
        // UI updates must run on MainThread
        textField.setText(event.message);
    }

    @Override
    public void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }

手動(dòng)獲取和移除sticky事件
就像前一段說(shuō)的那樣削葱,最后的sticky事件在訂閱者注冊(cè)的時(shí)候會(huì)自動(dòng)傳遞。但是淳梦,有時(shí)候手動(dòng)檢測(cè)sticky事件更方便析砸。有時(shí)候他們不再傳遞的時(shí)候需要移除sticky事件。比如:

MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
    // "Consume" the sticky event
    EventBus.getDefault().removeStickyEvent(stickyEvent);
    // Now do something with it
}

removeStickyEvent方法是超載的:當(dāng)傳入一個(gè)類爆袍,它會(huì)返回之前保持的sticky事件首繁。使用這中變化可以提升之前的例子。

MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
    // Now do something with it
}

優(yōu)先級(jí)和事件取消

大部分的EventBus都不需要優(yōu)先級(jí)或事件取消陨囊,但是它們?cè)谔厥馇闆r下會(huì)派上用場(chǎng)弦疮。比如,一個(gè)app在后臺(tái)運(yùn)行的時(shí)候一個(gè)事件觸發(fā)了一些UI的邏輯 蜘醋,但是如果app當(dāng)前對(duì)用戶是不可見(jiàn)的胁塞,那么應(yīng)該有不同的反應(yīng)。
訂閱者優(yōu)先級(jí)
可以通過(guò)在注冊(cè)期間提供的優(yōu)先級(jí)來(lái)改變事件傳遞的順序沙郭。

@Subscribe(priority = 1);
public void onEvent(MessageEvent event) {
…
}

在相同的傳遞線程(ThreadMode)鼻听,高優(yōu)先級(jí)的訂閱者接收事件會(huì)在低優(yōu)先級(jí)之前。默認(rèn)優(yōu)先級(jí)是0仙辟。
注意:優(yōu)先級(jí)不會(huì)對(duì)不同ThreadModes訂閱者之間的傳遞順序有影響扰才。
取消事件傳遞
在訂閱者事件處理方法中通過(guò)cancelEventDelivery(Object event)取消事件傳遞允懂。之后的任何事件傳遞都會(huì)取消:后續(xù)的訂閱者不會(huì)再接收到這個(gè)事件。

// Called in the same thread (default)
@Subscribe
public void onEvent(MessageEvent event){
// Process the event
…

EventBus.getDefault().cancelEventDelivery(event) ;
}

事件通常是被優(yōu)先級(jí)高的訂閱者取消衩匣。取消對(duì)于運(yùn)行在提交線程ThreadMode.PostThread的事件處理方法是被限制的累驮。

訂閱者索引

訂閱者索引(subscriber index)是EventBus3的新特性。這是個(gè)可選的優(yōu)化項(xiàng)來(lái)提速初始化訂閱者注冊(cè)舵揭。訂閱者索引可以使用EventBus的注解處理器在編譯階段創(chuàng)建谤专。雖然使用索引不是必須的,但是android最佳實(shí)踐還是推薦使用午绳。
索引先決條件
注意只有訂閱者和事件類是public置侍,@Subscriber方法才能被索引。由于java的注解本身處理的技術(shù)限制拦焚,@Subscribe注解不會(huì)被匿名內(nèi)部類識(shí)別蜡坊。當(dāng)EventBus不能使用索引的時(shí)候,它會(huì)自動(dòng)回退到在運(yùn)行時(shí)起作用赎败。所以它仍然起作用秕衙,只是慢了一點(diǎn)。
生成索引
為了能夠生成索引僵刮,需要在android-apt gradle插件的編譯環(huán)境添加EventBus注解處理器据忘。還需要傳遞一個(gè)參數(shù)為“eventBusIndex”到指定完全限定的想要生成索引的類。添加下面的部分到Gradle編譯腳本:

buildscript {
    dependencies {
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
    }
}
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
    compile 'org.greenrobot:eventbus:3.0.0'
    apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
apt {
    arguments {
        eventBusIndex "com.example.myapp.MyEventBusIndex"
    }
}

當(dāng)下次編譯工程的時(shí)候搞糕,“eventBusIndex”這個(gè)類會(huì)生成勇吊。當(dāng)設(shè)置EventBus的時(shí)候,只需要這樣:

EventBus eventBus = EventBus.builder().addIndex(new MyEventBusIndex()).build();

或者想使用默認(rèn)的實(shí)例窍仰,可以這樣:

EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
// Now the default instance uses the given index. Use it like this:
EventBus eventBus = EventBus.getDefault();

索引Libraries
應(yīng)用相同的原理來(lái)索引Library的一部分代碼(并不是最終的應(yīng)用程序)汉规。這樣,可以會(huì)生成多個(gè)索引類驹吮,在設(shè)置EventBus的時(shí)候這樣使:

EventBus eventBus = EventBus.builder()
    .addIndex(new MyEventBusAppIndex())
    .addIndex(new MyEventBusLibIndex()).build();

混淆

混淆器混淆方法名稱的時(shí)候针史,有可能會(huì)移除方法那些沒(méi)有調(diào)用的方法。因?yàn)橛嗛喎椒](méi)有被直接調(diào)用碟狞,混淆器會(huì)誤認(rèn)為他們沒(méi)有被使用啄枕。在ProGuard配置中使用下面的片段來(lái)保護(hù)訂閱者被移除:

-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}

注意:不管是否使用索引,都需要這么配置篷就。

AsyncExecutor

免責(zé)聲明:AsyncExecutor不是一個(gè)核心的utility類射亏。在處理后臺(tái)線程它也許會(huì)保存一些錯(cuò)誤代碼,但是它不是一個(gè)核心的EventBus類竭业。
AsyncExecutor像一個(gè)線程池智润,但是有錯(cuò)誤(異常)處理。錯(cuò)誤會(huì)拋出異常未辆,AsyncExecutor會(huì)在事件中包裹這些異常窟绷。
通常調(diào)用AsyncExecutor.create()方法在Application中來(lái)創(chuàng)建一個(gè)實(shí)例。實(shí)現(xiàn)RunnableEx接口來(lái)執(zhí)行咐柜。RunnableEx和Runnable不一樣兼蜈,RunnableEx會(huì)拋出異常。
如果RunnableEx的實(shí)現(xiàn)拋出一個(gè)異常拙友,它會(huì)在ThrowableFailureEvent中捕獲到为狸。
執(zhí)行的例子:

AsyncExecutor.create().execute(
  new RunnableEx {
    public void run throws LoginException {
      // No need to catch any Exception (here: LoginException)
      remote.login();
      EventBus.getDefault().postSticky(new LoggedInEvent());
    }
  }
}

接收的例子:

public void onEventMainThread(LoggedInEvent event) {
  // Change some UI
}

public void onEventMainThread(ThrowableFailureEvent event) {
  // Show error in UI
}

AsyncExecutor生成器
使用靜態(tài)的Async Executor來(lái)自定義Async Executor實(shí)例。它會(huì)返回一個(gè)生成器來(lái)自定義EventBus實(shí)例遗契,線程池辐棒,和失敗的事件類。
另一個(gè)可以自定義的選項(xiàng)是提供錯(cuò)誤事件上下文環(huán)境信息的執(zhí)行范圍牍蜂。比如漾根,一個(gè)錯(cuò)誤事件可能只關(guān)聯(lián)到一個(gè)指定的Activity實(shí)例或類。你自定義錯(cuò)誤事件實(shí)現(xiàn)了HasExecutionScope接口鲫竞,AsyncExecutor會(huì)自動(dòng)設(shè)置執(zhí)行范圍辐怕。這樣,訂閱者可以在它執(zhí)行范圍查詢錯(cuò)誤的事件并基于它做出相應(yīng)操作从绘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寄疏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子僵井,更是在濱河造成了極大的恐慌赁还,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驹沿,死亡現(xiàn)場(chǎng)離奇詭異艘策,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)渊季,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門朋蔫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人却汉,你說(shuō)我怎么就攤上這事驯妄。” “怎么了合砂?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵青扔,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng)微猖,這世上最難降的妖魔是什么谈息? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮凛剥,結(jié)果婚禮上侠仇,老公的妹妹穿的比我還像新娘。我一直安慰自己犁珠,他們只是感情好逻炊,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著犁享,像睡著了一般余素。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炊昆,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天溺森,我揣著相機(jī)與錄音,去河邊找鬼窑眯。 笑死屏积,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的磅甩。 我是一名探鬼主播炊林,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼卷要!你這毒婦竟也來(lái)了渣聚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤僧叉,失蹤者是張志新(化名)和其女友劉穎奕枝,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓶堕,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡隘道,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了郎笆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谭梗。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖宛蚓,靈堂內(nèi)的尸體忽然破棺而出激捏,到底是詐尸還是另有隱情,我是刑警寧澤凄吏,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布远舅,位于F島的核電站闰蛔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏图柏。R本人自食惡果不足惜序六,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爆办。 院中可真熱鬧难咕,春花似錦课梳、人聲如沸距辆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)跨算。三九已至,卻和暖如春椭懊,著一層夾襖步出監(jiān)牢的瞬間诸蚕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工氧猬, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留背犯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓盅抚,卻偏偏與公主長(zhǎng)得像漠魏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妄均,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評(píng)論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理柱锹,服務(wù)發(fā)現(xiàn),斷路器丰包,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • EventBus源碼分析(一) EventBus官方介紹為一個(gè)為Android系統(tǒng)優(yōu)化的事件訂閱總線禁熏,它不僅可以很...
    蕉下孤客閱讀 3,972評(píng)論 4 42
  • 人生幾何多, 醉酒伴到老邑彪。 苦書轉(zhuǎn)游離瞧毙, 青燈侯司稿。 雨落雪染纏寄症, 步旅風(fēng)塵浩升筏。 天若留別意, 萍水否相潮瘸爽。
    教青霜閱讀 317評(píng)論 0 0
  • 大二還沒(méi)開始 可是我還是要規(guī)劃一下啦 首先是學(xué)習(xí)上的 1.這學(xué)期要努力學(xué)習(xí) 把六級(jí)給過(guò)了 然后有空的時(shí)候多背背英語(yǔ)...
    默默的小獅子閱讀 883評(píng)論 0 1