EventBus的使用和原理在网上有很多的博客了,其中泓洋大哥和启舰写的非常非常棒,我也是跟着他们的博客学会的EventBus,因为是第一次接触并使用EventBus,所以我写的更多是如何使用,源码解析就不怎么样啦!
如需转载请注明出处:Android EventBus 3.0 实例使用详解
一、概述
compile ‘org.greenrobot:eventbus:3.0.0‘
(2)在相关Activity中的onCreat()、onDestory()注册和解注EventBus
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EventBus.getDefault().register(this); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); }
(3)事件发布者如何发布事件
EventBus.getDefault().post(实参);
我们到.getDefault()来看一个这个方法:
/** Convenience singleton for apps using a process-wide EventBus instance. */ public static EventBus getDefault() { if (defaultInstance == null) { synchronized (EventBus.class) { if (defaultInstance == null) { defaultInstance = new EventBus(); } } } return defaultInstance; }
这里的.getDefault()方法其实就是一个单例,获取到EventBus实例后调用post方法开始发布事件
post():
/** Posts the given event to the event bus. */ public void post(Object event) { PostingThreadState postingState = currentPostingThreadState.get(); List<Object> eventQueue = postingState.eventQueue; eventQueue.add(event); if (!postingState.isPosting) { postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper(); postingState.isPosting = true; if (postingState.canceled) { throw new EventBusException("Internal error. Abort state was not reset"); } try { while (!eventQueue.isEmpty()) { postSingleEvent(eventQueue.remove(0), postingState); } } finally { postingState.isPosting = false; postingState.isMainThread = false; } } }
通过源码可以看得出来,方法的实参是一个对象类型的参数,参数会统一存储在eventQueue这个队列中,然后循环队列,将队列中的消息逐一发布,这里大家可能会想,每次post都会去调用整个队列么,那么不会造成方法多次调用么?
答案是不会的,因为在最外层加了一个判断,判断event是否被发不过,如果被发布过,则不会进入到这个方法内。
(4)事件订阅者订阅事件
@Subscribe public void onEventMainThread(实参){ //接收到发布者发布的事件后,进行相应的处理操作 }
这里要注意的是:EventBus在 3.0 版本后,事件订阅监听的方法名可以随意起,不同于旧版本,名字是特定的。
public void onEventMainThread(param) {
//如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,
//这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。 } public void onEventPostThread(param) { //如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。
//使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。 } public void onEventBackgroundThread(param) { //如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。 } public void onEventAsync(param) { //使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync. }
但是新版本需要手动的添加注解@Subscribe(这是必不可少的)。既然名字可以随意起,那么又怎么控制在什么线程内进行处理呢?
@Subscribe(threadMode = ThreadMode.MAIN)
给注解设置ThreadMode就可以了。
(5)事件发布者和订阅者如何对应上
可以看到发布事件和订阅事件,都需要传入一个实参,而且在post方法中我们也看到了,这个实参是对象类型的,大家猜想的话也可以知道,发布和订阅事件是通过一个对象实参来进行关联的。
public class TestEvent { private int mMsg; public TestEvent(int msg) { mMsg = msg; } public int getMsg(){ return mMsg; } }
这个类很简单,只有一个变量和一个构造方法、get方法。具体内容根据项目需求来定。
基本上了解这些就可以搞明白EventBus的使用了,下面上一下我写的Demo,功能很简单,就是模仿下载的进度条,因为现在用的最多的是通过handler来进行处理的,而EventBus的出现,可以完美的代替handler,
而且实现了解耦。
好,上代码!
MainActivity.class
package com.example.wgh.eventbusdemo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.ProgressBar; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; public class MainActivity extends Activity { public ProgressBar progressBar = null; public int time = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { while (time<100){ time += 15; EventBus.getDefault().post(new TestEvent(time)); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }); progressBar = (ProgressBar) findViewById(R.id.progressbar); EventBus.getDefault().register(this); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } @Subscribe(threadMode = ThreadMode.MAIN) public void onEventMainThread(TestEvent event){ progressBar.setProgress(event.getMsg()); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.wgh.eventbusdemo.MainActivity" android:orientation="vertical"> <ProgressBar android:id="@+id/progressbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="150dp" android:max="100" style="@style/Widget.AppCompat.ProgressBar.Horizontal"/> <Button android:id="@+id/button" android:layout_marginTop="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="开始下载"/> </LinearLayout>
TestEvent.class
public class TestEvent { private int mMsg; public TestEvent(int msg) { mMsg = msg; } public int getMsg(){ return mMsg; } }
原文:http://www.cnblogs.com/upwgh/p/6394901.html