EventBus的使用

EventBus使用

在介紹EventBus之前先捋順以下Android自帶的應用內通信方式有哪些?

Android 應用內常用通信方式

1.使用handler進行線程間通信

handler是和Thread綁定的,主線程中創建Hander直接通過new Handler() 來創建即可。自定義線程中則還需要調用Looper.prepare Looper.loop來讓Handler起作用,這裏就不詳細講解原理及使用了,感興趣的自己去探索一下。

Handler主要有兩個作用,一個是線程間傳遞消息, 另一個則是post Runnable對象,讓Runnable對象在Handler對應的那個線程裏運行。
下面用最小代碼簡單介紹展示一下Handler在線程間傳遞消息的方式。

示例代碼:
新建一個線程,延遲1s後通過主線程的Handler發送消息。
主線程的Handler收到消息後,打印log

public class MainActivity extends Activity{

    private  Handler mHandler;
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button) findViewById(R.id.button1);
        mHandler=new Handler(){

            @Override
            public void handleMessage(Message msg) {
                if(msg.what==0xff){
                    Log.e("what", "I got the Message");
                }
            }

        };

        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        mHandler.sendEmptyMessage(0xff);

                    }
                }).start();
            }
        });
    }

}

2.使用Interface定義回調,可以用在任意兩個對象之間。比如Activity和Fragment通信

Android官方的Guides也是這麼建議的
參考(http://developer.android.com/guide/components/fragments.htmlhttp://developer.android.com/training/basics/fragments/communicating.html

public static class FragmentA extends ListFragment {
    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    //在Fragment的onAttach方法中,綁定mListener(也就是需要實現了該接口的Activity)
     @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    //當Fragment中的Item點擊後,回調OnArticleSelectedListener的方法。Activity中實現的方法中即可做相應處理
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Append the clicked item's row ID with the content provider Uri
        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
        // Send the event and Uri to the host activity
        mListener.onArticleSelected(noteUri);
    }

}

在Activity中需要實現FragmentA中的OnArticleSelectedListener接口
public class MainActivity extends Activity implements FragmentA.OnArticleSelectedListener{
@Override
public void onArticleSelected(Uri articleUri) {
//Do something to response the Item selection
}

}

使用Intent進行組件間的通信

通過Intent來比如啓動Service,啓動Activity,
通過Intent來發送Broadcast,然後註冊一個BroadcastReceiver來接收並處理Intent. 這個部分比較基礎,就不再贅述了。

EventBus進行應用內通信

如果想深入瞭解EventBus的實現原理,可以參考 EventBus 源碼解析

簡介

EventBus是Android端的一個訂閱/發佈的消息總線,用在應用程序內,組件之間,線程之間的通信,並且由於事件可以是任意類型的對象,所以使用起來更加的方便快捷。
角色:
Event:就是事件啦
Subscriber:訂閱者,接收特定事件的對象,主要通過onEventXXX()回調接口接收
Publisher:發佈者,post事件,通知訂閱者

其他的先不多介紹了,後面慢慢展開。

使用過程

使用EventBus只有簡單的4步
- 1 定義一個Event事件
- 2 註冊一個訂閱者
- 3 發佈一個事件
- 4 接受這個事件

用代碼實現這4步就是:
- 1 public class MyEvent()–可以是任意Object
- 2 EventBus.getDefault().register(this)—比如這時一個Activity,那就等於把Activity註冊爲一個訂閱者
- 3 EventBus.getDefault().post(event)—隨便哪個組件或者線程中發送出一個MyEvent的對象
- 4 public void onEvent(MyEvent event)–第2步中的Activity中的onEvent方法接收到該事件並處理。注意一定Event類型要對應。如果寫成了onEvent(Object event),那就是post什麼類型的Event都能接受了。

看起來的確很方便。下面給出一個Activity中的完整代碼。也是比較簡單,但是能夠很清晰的看出EventBus是如何使用的。

示例代碼

public class MainActivity extends Activity{

    private TextView textView;
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button) findViewById(R.id.button1);
        textView= (TextView) findViewById(R.id.textView1);
        //1.註冊訂閱者
        EventBus.getDefault().register(this);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
            //post事件
                EventBus.getDefault().post(new MyEvent());
            }
        });
    }
    //接收事件的回調
    public void onEvent(MyEvent event){
        Log.e("What", "[onEvent]My Thread is "+Thread.currentThread().getName());
    }

自定義的事件就是一個空的類,當然也可以加入不同的屬性,方法。用來傳遞信息。

public class MyEvent {
}

點擊按鈕後可以看到TextView的內容已更改。

Log

03-29 18:56:22.738: E/What(17402): [onEvent]My Thread is main

onEventXXXX

onEvent函數一共有四種,前面的例子只用到一個onEvent。

函數名 含義 ThreadMode
onEvent 事件處理在事件發送的那個線程執行 PostThread
onEventMainThread 事件在主線程-UI線程執行 MainThread
onEventBackgroundThread 事件在一個後臺線程執行(就一個後臺線程) BackgroundThread
onEventAsync 事件會單獨啓動一個線程執行(每個事件都會啓動一個線程) Async

其中前三個事件處理方式,都應該儘快完成。

onEventMainThread使用演示

onEventMainThread就是會放到主線程去執行的事件處理,一般在其中進行比如UI的更新的操作,比如TextView的更改。下面通過代碼展示一下。一個自定義的線程發送該事件,Activity通過onEventMainThread接收到該事件,並更新UI.這個時候就不能使用onEvent了,因爲根據上表所示,onEvent會放在發送事件的那個線程中去執行,其實不能進行UI更新操作的。

示例代碼

public class MainActivity extends Activity{

    private TextView textView;
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button) findViewById(R.id.button1);
        textView= (TextView) findViewById(R.id.textView1);
        //1.註冊訂閱者
        EventBus.getDefault().register(this);
        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        EventBus.getDefault().post(new MyEvent());              
                    }
                }).start();
            }
        });
    }

    public void onEvent(MyEvent event){
        Log.e("What", "[onEvent]My Thread is "+Thread.currentThread().getName());
    }
    public void onEventMainThread(MyEvent event){
        Log.e("What", "[onEventMainThreadMy] Thread is "+Thread.currentThread().getName());
        textView.setText("onEventMainThread called");
    }

}

點擊按鈕後可以看到TextView的內容已更改。

Log

03-29 18:54:10.728: E/What(16993): [onEvent]My Thread is Thread-67572
03-29 18:54:10.778: E/What(16993): [onEventMainThreadMy] Thread is main

Sticky Event

Sticky Event是指我註冊一個sticky的訂閱,這樣註冊之前發送的sticky事件的最近的一個會保存在內存中,錯過這個事件的發送的情況下,也可以通過getStickyEvent收到。

  • postSticky(event) :發送sticky的event
  • registerSticky(subscriber) :註冊接收sticky事件的訂閱者
  • getStickyEvent(Class

示例代碼

public class MyEvent {
    public String what;

    public MyEvent(String what) {
        super();
        this.what = what;
    }

}
package com.example.eventbusdemo;

import de.greenrobot.event.EventBus;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

    private TextView textView;
    private Button sendEvent;
    private Button quaryEvent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sendEvent = (Button) findViewById(R.id.button1);
        quaryEvent = (Button) findViewById(R.id.button2);
        textView = (TextView) findViewById(R.id.textView1);
        // 1.註冊訂閱者
        EventBus.getDefault().registerSticky(this);
        sendEvent.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // 點擊按鍵發送5個Sticky event
                for (int i = 0; i < 5; i++) {
                    EventBus.getDefault().postSticky(
                            new MyEvent(String.valueOf(i)));
                }

            }
        });

        quaryEvent.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                MyEvent lastEvent = EventBus.getDefault().getStickyEvent(
                        MyEvent.class);
                Log.e("What", "[quaryEvent] last Event is" + lastEvent.what);
            }
        });
    }

    public void onEvent(MyEvent event) {
        Log.e("What", "[onEvent] this Event is" + event.what);
    }
}

結果

點擊sendEvent按鈕:
Log

03-29 19:09:40.698: E/What(20520): [onEvent] this Event is0
03-29 19:09:40.698: E/What(20520): [onEvent] this Event is1
03-29 19:09:40.698: E/What(20520): [onEvent] this Event is2
03-29 19:09:40.698: E/What(20520): [onEvent] this Event is3
03-29 19:09:40.698: E/What(20520): [onEvent] this Event is4

點擊quaryEvent按鈕:
Log

03-29 19:12:31.578: E/What(20520): [quaryEvent] last Event is4

技巧

Event類一般都比較小,所以可以把它們都打包在一個Events類中。比如:

public class Events{
    public static class AbcEvent{
    }
    public static class XyzEvent{
    }
}
發佈了88 篇原創文章 · 獲贊 5 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章