EventBus_事件传递框架

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liangjingkanji/article/details/54096842

EventBus

由greenRobot公司开发, 目的是简化开发中的事件传递.

优点

  1. 注释没有使用反射, 在编译时完成注解解析不影响程序性能
  2. 代码简单, 使用注解简化了代码量,代码逻辑更加清晰
  3. 简化组件通讯, 在不同的activity等组件之间方便的传递事件
  4. 优化线程传递, 在不同的线程处理事件(例如ui或者耗时操作)不再需要考虑线程切换使用AsyncTask之类的方法

演示

EventBus由三部分组成: 事件类, 注册事件订阅者, 发送事件

  1. 添加依赖

    compile 'org.greenrobot:eventbus:3.0.0'
  2. 定义事件类

    “`java
    public class EventTest {

    String message;
    public EventTest(String message) {
      this.message = message;
    }
    

    }
    “`

  3. 注册事件订阅者

    “`java
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

             // 创建单例对象注册此activity
             EventBus.getDefault().register(this);
           }
    
        /**
    
    • 在EventBus发送事件时被调用
    • 方法名随意, 只要加上@Subscribe注释即可
      *
    • @param eventTest 接受被发送的事件类
      */
      @Subscribe
      public void casualName(EventTest eventTest) {
      Toast.makeText(this, eventTest.message, Toast.LENGTH_SHORT).show();
      }
      “`
  4. 发送事件

    // 该方法可以在任意类中被使用, 向被注册的类发送事件
    EventBus.getDefault().post(new EventTest(5));

Sticky粘性事件

如果用上面的方法直接向下一个界面的activity发送事件, 将会出现找不到订阅者的警告. 但是第二次进入又会执行事件订阅者, 但是依然无法在订阅者内修改任何UI, 因为收到的是上一个被销毁的界面的事件.

为了解决这种发送事件和接收事件无法达到匹配的问题就得使用EventBus的粘性事件

发送粘性事件

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

接收粘性事件

@Override
public void onStart() {
    super.onStart();
  // 这一句必须在register方法之前执行, 否则在订阅者中使用这个控件会导致空指针, 但不会造成程序挂掉
  mViewById = (TextView) findViewById(R.id.textView);
    EventBus.getDefault().register(this);
}

// UI 更新必须在主线程
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN) // 注意Subsctibe的参数变更
public void onEvent(MessageEvent event) {   
    textField.setText(event.message);
}

要注意的是在订阅者中操作的数据必须在register注册事件之前初始化完成

直接得到事件类

如果只是想得到事件类还可以使用更加方便的获取方式

EventTest eventTest = EventBus.getDefault().getStickyEvent(EventTest.class);

线程通讯

EventBus能做到自动处理线程切换, 只需要使用不同的线程模式即可实现订阅者在不同的线程执行操作, 如果涉及到子线程, 将开启线程池.但是如果是在子线程发送的事件将不会开启线程池, 且只有写在主线程的订阅者才是能接收事件的订阅者

线程模式

  1. POSTING
  2. MAIN
  3. BACKGROUND
  4. ASYNC
/**
* 默认线程模式, 和@Subscribe一样, 在发送者所在线程执行事件
*
* @param eventTest 事件类
*/
@Subscribe(threadMode = ThreadMode.POSTING)
public void defaultEvent(EventTest eventTest) {
  Log.i("日志", "defaultEvent >>> " + Thread.currentThread().getName());
}

/**
* 在子线程执行事件, 如果发送者在子线程将不会新建子线程
*
* @param eventTest
*/
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void backgroundEvent(EventTest eventTest) {
  Log.i("日志", "backgroundEvent >>> " + Thread.currentThread().getName());
}

/**
* 无论发送者在子线程亦或主线程都将会新建一个子线程执行事件
* 
* @param eventTest
*/
@Subscribe(threadMode = ThreadMode.ASYNC)
public void AsyncEvent(EventTest eventTest) {
  Log.i("日志", "MainActivity.AsyncEvent_68 >>> " + Thread.currentThread().getName());
}

只需要使用不同的订阅者注解即可在不同的线程之间切换事件传递

猜你喜欢

转载自blog.csdn.net/liangjingkanji/article/details/54096842