安卓開發筆記——探索EventBus


1、關於EventBus:

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

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

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

  EventBus的大體關系是這樣的:訂閱者(Subscriber)通過訂閱事件(Event)到總線,事件發布者(Publisher)發布事件(Event)到總線被訂閱者(Subscriber)接收,其實說白了就是軟件設計模式里的觀察者模式。EventBus在使用的時候就是在合適的地方發布一個事件,使得注冊了該事件接收的對象就可以收到通知,進行相應的操作。

2、初探EventBus:

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

  

  看似很簡單的效果,點擊按鈕跳轉界面,利用Intent發送一個消息,然后TextView接收顯示。這是傳統上的做法,如果真是這樣做,那么寫這篇文章的就完全沒意義了。其實這里就是利用到了EventBus,並沒有用到Intent來傳遞消息。

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

 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

  上面的代碼很簡單,這里只是拋磚引玉並不做太多復雜的操作,大家可以根據自己的項目需求來添加對應的代碼。

3、解析代碼:

1、注冊EventBus: 

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

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

 

2、EventBus事件:

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

 

3、EventBus事件發布者:

  有了事件之后,我們就可以對事件進行發布,然后可以被訂閱這個事件的所有訂閱者所接收。發送事件很簡單,有兩種方法post與postSticky:

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

 

4、EventBus事件訂閱者:

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

  1、onEvent:

  如果使用onEvent作為訂閱函數,那么該事件在哪個線程發布出來的,onEvent就會在這個線程中運行,也就是說發布事件和接收事件線程在同一個線程。使用這個方法時,在onEvent方法中不能執行耗時操作,如果執行耗時操作容易導致事件分發延遲。
  2、onEventMainThread:

  如果使用onEventMainThread作為訂閱函數,那么不論事件是在哪個線程中發布出來的,onEventMainThread都會在UI線程中執行,接收事件就會在UI線程中運行,這個在Android中是非常有用的,因為在Android中只能在UI線程中跟新UI,所以在onEvnetMainThread方法中是不能執行耗時操作的。
  3、onEventBackground:

  如果使用onEventBackgrond作為訂閱函數,那么如果事件是在UI線程中發布出來的,那么onEventBackground就會在子線程中運行,如果事件本來就是子線程中發布出來的,那么onEventBackground函數直接在該子線程中執行。
  4、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方法發布。

 

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

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

  例如:

  1、當某個頁面的某些值發生變化的時候,需要去同時去更改多個頁面相對應的值,這時候只要這些類注冊訂閱了該事件,那么我們就可以很輕松通過post發送消息來進行通訊。

  2、某些時候,我們並不希望發布出來的Event立即被消費掉,而是等到時機成熟。比如說,在一個詳情頁點贊之后,產生一個事件,這個事件並不立即被消費,而是等用戶退出詳情頁回到商品列表之后,接收到該事件,然后刷新Adapter等。其實這就是之前我們用startActivityForResult和onActivityResult做的事情。這里我們就可以利用postSticky來實現這樣的機制。

  總之,EventBus極大的減輕了我們各種組件之間的通訊復雜度,也大大減少了使用ActivityForResult的麻煩。真實值得極力推薦。

 

5、理解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/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,日后必有一番作為!旁邊有“推薦”二字,你就順手把它點了吧,相得准,我分文不收;相不准,你也好回來找我!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM