安卓開發筆記——探索EventBus

一、關於EventBus:java

組件通信在Android開發中是不可避免的,隨着業務需求的複雜化,代碼中須要咱們去處理的業務邏輯難度也不斷增大。例如多個Fragment之間的數據傳遞,Service與Activity、Fragment之間的通信,BroadCast與Activity、Fragment之間的通信,各類startActivityForResult的使用,繁雜的操做令咱們所厭倦,在GitHub上找了下解決方案,發現了一個不錯的開源庫EventBus,相信不少作過Android開發的朋友都或多或少對此有所瞭解。android

  EventBus是一款針對Android優化的發佈/訂閱事件總線。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,線程之間傳遞消息.優勢是開銷小,代碼更優雅。以及將發送者和接收者解耦。git

  這是EventBus在GitHub上的開源庫地址:https://github.com/greenrobot/EventBusgithub

  EventBus的大致關係是這樣的:訂閱者(Subscriber)經過訂閱事件(Event)到總線,事件發佈者(Publisher)發佈事件(Event)到總線被訂閱者(Subscriber)接收,其實說白了就是軟件設計模式裏的觀察者模式。EventBus在使用的時候就是在合適的地方發佈一個事件,使得註冊了該事件接收的對象就能夠收到通知,進行相應的操做。設計模式

二、初探EventBus:app

  文縐縐的文字描述使人厭煩,直接上代碼說話吧,先來看下要實現的效果:ide

  

  看似很簡單的效果,點擊按鈕跳轉界面,利用Intent發送一個消息,而後TextView接收顯示。這是傳統上的作法,若是真是這樣作,那麼寫這篇文章的就徹底沒意義了。其實這裏就是利用到了EventBus,並無用到Intent來傳遞消息。函數

  先來看下具體的代碼(記得添加EventBus的引用),而後我再分部來解析:post

 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
 2 
 3 import android.content.Intent;
 4 import android.os.Bundle;
 5 import android.support.v7.app.AppCompatActivity;
 6 import android.view.View;
 7 import android.widget.Button;
 8 import android.widget.TextView;
 9 
10 import de.greenrobot.event.EventBus;
11 
12 public class MainActivity extends AppCompatActivity {
13 
14     private Button mBt_1;
15     private TextView mTv_1;
16 
17     @Override
18     protected void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.activity_main);
21         //註冊綁定EventBus
22         EventBus.getDefault().register(this);
23 
24         initView();
25         initAction();
26 
27     }
28 
29     private void initAction() {
30         mBt_1.setOnClickListener(new View.OnClickListener() {
31             @Override
32             public void onClick(View v) {
33                 startActivity(new Intent(MainActivity.this, SecondActivity.class));
34             }
35         });
36     }
37 
38     private void initView() {
39         mBt_1 = (Button) findViewById(R.id.bt_1);
40         mTv_1 = (TextView) findViewById(R.id.tv_info1);
41     }
42 
43 
44     //接收所訂閱的消息
45     public void onEventMainThread(MyEvent myEvent) {
46         if (myEvent.getInfo()!=null) {
47             mTv_1.setText(myEvent.getInfo());
48         }
49 
50     }
51 
52 
53     @Override
54     protected void onDestroy() {
55         super.onDestroy();
56         //解綁EventBus
57         EventBus.getDefault().unregister(this);
58     }
59 }
MainActivity.java
 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
 2 
 3 import android.os.Bundle;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.view.View;
 6 import android.widget.Button;
 7 import android.widget.Toast;
 8 
 9 import de.greenrobot.event.EventBus;
10 
11 public class SecondActivity extends AppCompatActivity {
12 
13     private Button mBt_2;
14 
15     @Override
16     protected void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.activity_second);
19         initView();
20         initAction();
21 
22     }
23 
24     private void initAction() {
25         mBt_2.setOnClickListener(new View.OnClickListener() {
26             @Override
27             public void onClick(View v) {
28                 Toast.makeText(SecondActivity.this,"消息已發送",Toast.LENGTH_SHORT).show();
29                 EventBus.getDefault().post(new MyEvent("我是被髮送過來的消息"));
30 
31             }
32         });
33     }
34 
35     private void initView() {
36         mBt_2 = (Button) findViewById(R.id.bt_2);
37     }
38 
39 
40 }
SecondActivity.java
 1 package com.lcw.rabbit.eventbusdemo.eventbusdemo;
 2 
 3 /**
 4  * Created by Lichenwei
 5  * Date: 2015-10-11
 6  * Time: 18:23
 7  */
 8 public class MyEvent {
 9 
10     private String info;
11 
12     public MyEvent(String info) {
13         this.info = info;
14     }
15 
16     public String getInfo() {
17         return info;
18     }
19 
20     public void setInfo(String info) {
21         this.info = info;
22     }
23 }
MyEvent

  上面的代碼很簡單,這裏只是拋磚引玉並不作太多複雜的操做,你們能夠根據本身的項目需求來添加對應的代碼。優化

三、解析代碼:

一、註冊EventBus: 

  在添加EventBus的引用後,咱們就能夠對任意類進行註冊綁定和解綁EventBus事件,註冊方法和反註冊方法很簡單,在上面的代碼中就能夠看出來了,分別是register和unregister,這裏的EventBus.getDefault是獲取到EventBus實例的意思(單例)。

1 //註冊綁定EventBus
2 EventBus.getDefault().register(this);
3 //解綁EventBus
4 EventBus.getDefault().unregister(this);

 

二、EventBus事件:

  EventBus很靈活,它對事件不進行任何的限制,也不須要繼承或者實現任何類或者接口,能夠是任意類型的實體類,比如上面代碼提到的MyEvent。

 

三、EventBus事件發佈者:

  有了事件以後,咱們就能夠對事件進行發佈,而後能夠被訂閱這個事件的全部訂閱者所接收。發送事件很簡單,有兩種方法post與postSticky:

1 //當即發送事件 
2 EventBus.getDefault().post(Object event);
3 //延遲發送事件
4 EventBus.getDefault().postSticky(Objet event);

 

四、EventBus事件訂閱者:

  EventBus的事件訂閱者能夠是任何已經進行註冊EventBus的類,訂閱者的數量是沒有上限的(很重要,下文會提到),這裏的訂閱有4種方法,這裏都是由onEvent開頭的,有着必定的區別:

  一、onEvent:

  若是使用onEvent做爲訂閱函數,那麼該事件在哪一個線程發佈出來的,onEvent就會在這個線程中運行,也就是說發佈事件和接收事件線程在同一個線程。使用這個方法時,在onEvent方法中不能執行耗時操做,若是執行耗時操做容易致使事件分發延遲。
  二、onEventMainThread:

  若是使用onEventMainThread做爲訂閱函數,那麼不論事件是在哪一個線程中發佈出來的,onEventMainThread都會在UI線程中執行,接收事件就會在UI線程中運行,這個在Android中是很是有用的,由於在Android中只能在UI線程中跟新UI,因此在onEvnetMainThread方法中是不能執行耗時操做的。
  三、onEventBackground:

  若是使用onEventBackgrond做爲訂閱函數,那麼若是事件是在UI線程中發佈出來的,那麼onEventBackground就會在子線程中運行,若是事件原本就是子線程中發佈出來的,那麼onEventBackground函數直接在該子線程中執行。
  四、onEventAsync:

  使用這個函數做爲訂閱函數,那麼不管事件在哪一個線程發佈,都會建立新的子線程在執行onEventAsync。

1  public void onEvent(Object event) {}
2  public void onEventMainThread(Object event) {}
3  public void onEventBackgroundThread(Object event) {}
4  public void onEventAsync(Object event) {}

  介紹完EventBus裏的全部角色後,咱們來理一理訂閱/被訂閱流程:

  首先,要想成爲事件訂閱者須要先對EventBus進行註冊綁定,而後在本類須要去寫一個以onEvent開頭的方法來接收處理消息事件,再來咱們須要一個自定義的事件可讓事件的發佈者發佈,讓事件的訂閱者接收。事件的發佈能夠經過post方法或者是postSticky方法發佈。

 

四、EventBus所帶來的一些方便之處:

  EventBus是一款針對Android優化的發佈/訂閱事件總線。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,線程之間傳遞消息.優勢是開銷小,代碼更優雅。以及將發送者和接收者解耦。這是咱們在文章開頭所介紹過的,這裏就很少說了,說幾個在實際開發中所運用到的地方。

  例如:

  一、當某個頁面的某些值發生變化的時候,須要去同時去更改多個頁面相對應的值,這時候只要這些類註冊訂閱了該事件,那麼咱們就能夠很輕鬆經過post發送消息來進行通信。

  二、某些時候,咱們並不但願發佈出來的Event當即被消費掉,而是等到時機成熟。好比說,在一個詳情頁點贊以後,產生一個事件,這個事件並不當即被消費,而是等用戶退出詳情頁回到商品列表以後,接收到該事件,而後刷新Adapter等。其實這就是以前咱們用startActivityForResult和onActivityResult作的事情。這裏咱們就能夠利用postSticky來實現這樣的機制。

  總之,EventBus極大的減輕了咱們各類組件之間的通信複雜度,也大大減小了使用ActivityForResult的麻煩。真實值得極力推薦。

 

五、理解EventBus

  從源碼中咱們能夠知道,當咱們在類中註冊綁定EventBus的時候,它會去掃描當前類並記錄下全部已onEvent開頭的方法,存放在一個Map<Key,Value>中,在事件經過post發佈以後,EventBus會根據post中實參的類型,去Map中查找對應的方法,並找到了對應的Thread,最終利用Java的反射機制去執行咱們的方法。

  onEventMainThread表示這個方法會在UI主線程執行。

  onEventPostThread表示這個方法會在當前發佈事件的線程中執行。

  BackgroundThread表示若是在非UI主線程發佈的事件,則直接執行,和發佈在同一個線程中。若是在UI線程發佈的事件,則加入後臺任務隊列,使用線程池一個接一個調用。

  Async 加入後臺任務隊列,使用線程池調用,注意沒有BackgroundThread中的一個接一個。

 

做者:李晨瑋
出處:http://www.cnblogs.com/lichenwei/本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,往後必有一番做爲!旁邊有「推薦」二字,你就順手把它點了吧,相得準,我分文不收;相不許,你也好回來找我!

相關文章
相關標籤/搜索