EventBus3.0使用介绍

EventBus3.0使用介绍

前言:之前组件间通信一直用动态广播的方式。主要是点赞状态的更新。
不太喜欢接口回调,因为有点繁琐,逻辑上不好理解和维护。所以简答的需求,基本上广播就可以满足了,当然广播还有一些高级功能,静态注册、普通广播、有序广播、粘性广播(滞留广播)、本地广播、广播的优先级、广播分发拦截。一般本地广播就可以实现应用内部组件间的通信。本地广播和其他两个广播的区别是:本地广播只在本应用中生效。普通广播和无序广播作用全局。

  • 动态广播:广播的方式,很好理解和维护。但是代码量稍微有点多。

    发送广播:

    Intent intent = new Intent();
    intent.setAction("updatePostCommoList");//标识广播
    intent.putExtra("childBean",childBean);//携带数据
    LocalBroadcastManager.getInstance(this)
            .sendBroadcast(intent);//获取广播单例。进行发送广播
    

    接受广播:

    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager
            .getInstance(getActivity());
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction("updateFragment");
    intentFilter.addAction("updateUserAllMessage");
    BroadcastReceiver br = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("updateFragment")) {
               //根据不同标识,doSomething
            }
        }
    
    };
    localBroadcastManager.registerReceiver(br, intentFilter);
    
  • EventBus3.0 :稍微比广播代码量少点,但是得引入第三方库(50k)。现在这个代码量爆炸得年代,50k还能接受

使用方式

  1. 在需要订阅得地方,进行注册,解除注册

    @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);
    }
    
  2. 事件订阅

     @Subscribe(threadMode = ThreadMode.POSTING)
     public void helloEventBus(Person message){       
         Log.e("weiwei", "POSTING_helloEventBus: "+Thread.currentThread().getName() );
         mTextView.setText(message.getName());
     }
    
  3. 发送事件

     EventBus.getDefault().post(person);
    

ThreadMode有四种模式:

  • ThreadMode.POSTING:如果使用POSTING作为订阅注解参数,那么该事件在哪个线程发布出来的,helloEventBus就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在helloEventBus方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
  • ThreadMode.MAIN:如果使用MAIN作为订阅注解参数,那么不论事件是在哪个线程中发布出来的,helloEventBus都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在android中只能在UI线程中跟新UI,所以在helloEventBus方法中是不能执行耗时操作的。
  • ThreadMode.BACKGROUND:如果使用BACKGROUND作为注解参数,那么如果事件是在UI线程中发布出来的,那么helloEventBus就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么helloEventBus函数直接在该子线程中执行。
  • ThreadMode.ASYNC:使用ASYNC作为订阅注解参数,那么无论事件在哪个线程发布,都会创建新的子线程在执行helloEventBus。

使用进阶

上面的基本使用方式,基本上可以满足大部分需要。EventBus还有更高级的功能,实现复杂的逻辑。基本上和广播一样,事件的优先级、事件拦截。

订阅事件的优先级

 @Subscribe(threadMode = ThreadMode.POSTING,priority = 100)
public void helloEventBus(Person message){
    Log.e("weiwei", "POSTING_helloEventBus: "+Thread.currentThread().getName() );
    mTextView.setText(message.getName());
}
@Subscribe(threadMode = ThreadMode.MAIN,priority = 101)
public void hello1EventBus(Person message){
    Log.e("weiwei", "MAIN_helloEventBus: "+Thread.currentThread().getName() );
    mTextView1.setText(message.getName());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND,priority = 102)
public void hello2EventBus(Person message){
    Log.e("weiwei", "BACKGROUND_helloEventBus: "+Thread.currentThread().getName() );
    mTextView2.setText(message.getName());
}
@Subscribe(threadMode = ThreadMode.ASYNC,priority = 103)
public void hello3EventBus(Person message){
    Log.e("weiwei", "ASYNC_helloEventBus: "+Thread.currentThread().getName() );
    mTextView3.setText(message.getName());
}

结果:
ASYNC_helloEventBus: pool-2-thread-4
BACKGROUND_helloEventBus: pool-2-thread-4
MAIN_helloEventBus: main
POSTING_helloEventBus: main

事件拦截

 @Subscribe(threadMode = ThreadMode.ASYNC,priority = 103)
    public void hello3EventBus(Person message){
        EventBus.getDefault().cancelEventDelivery(mPerson) ;
        Log.e("weiwei", "ASYNC_helloEventBus: "+Thread.currentThread().getName() );
        mTextView3.setText(message.getName());
    }

结果:
BACKGROUND_helloEventBus: pool-2-thread-1
MAIN_helloEventBus: main
POSTING_helloEventBus: main

这个结果和有序广播的拦截机制不一样,哪个订阅事件拦截了,他就不会在接受这个事件。感觉有点鸡肋。

EventBus黏性事件

EventBus除了普通事件也支持粘性事件,这个有点类似广播分类中的粘性广播。本身粘性广播用的就比较少,为了方便理解成订阅在发布事件之后,但同样可以收到事件。订阅/解除订阅和普通事件一样,但是处理订阅函数有所不同,需要注解中添加sticky = true

@Subscribe(threadMode = ThreadMode.MAIN,sticky = true) //在ui线程执行
public void onDataSynEvent(DataSynEvent event) {
    Log.e(TAG, "event---->" + event.getCount());
}

发送粘性事件

EventBus.getDefault().postSticky(new DataSynEvent());

对于粘性广播我们都比较清楚属于常驻广播,对于EventBus粘性事件也类似,我们如果不再需要该粘性事件我们可以移除

EventBus.getDefault().removeStickyEvent(new DataSynEvent());

或者调用移除所有粘性事件

 EventBus.getDefault().removeAllStickyEvents();

EventBus processor使用

EventBus提供了一个EventBusAnnotationProcessor注解处理器来在编译期通过读取@Subscribe()注解并解析,
处理其中所包含的信息,然后生成java类来保存所有订阅者关于订阅的信息,这样就比在运行时使用反射来获得这些订阅者的
信息速度要快.

  1. 具体使用:在build.gradle中添加如下配置

    buildscript {
    dependencies {
          classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
     }
    }
    apply plugin: 'com.neenbedankt.android-apt'
    
    dependencies {
        compile 'org.greenrobot:eventbus:3.0.0'
        apt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
    }
    apt {
        arguments {
            eventBusIndex "com.whoislcj.eventbus.MyEventBusIndex"
        }
    }
    
  2. 使用索引
    此时编译一次,自动生成生成索引类。在\build\generated\source\apt\PakageName\下看到通过注解分析生成的索引类,这样我们便可以在初始化EventBus时应用我们生成的索引了。
    自动生成的代码

        /** This class is generated by EventBus, do not edit. */
    public class MyEventBusIndex implements SubscriberInfoIndex {
        private static final Map, SubscriberInfo> SUBSCRIBER_INDEX;
    
        static {
            SUBSCRIBER_INDEX = new HashMap, SubscriberInfo>();
    
            putIndex(new SimpleSubscriberInfo(com.whoislcj.testhttp.MainActivity.class, true, new SubscriberMethodInfo[] {
                new SubscriberMethodInfo("onDataSynEvent", com.whoislcj.testhttp.eventBus.DataSynEvent.class,
                        ThreadMode.MAIN, 100, false),
                new SubscriberMethodInfo("onDataSynEvent1", com.whoislcj.testhttp.eventBus.TestEvent.class, ThreadMode.MAIN,
                        0, true),
            }));
    
        }
    
        private static void putIndex(SubscriberInfo info) {
            SUBSCRIBER_INDEX.put(info.getSubscriberClass(), info);
        }
    
        @Override
        public SubscriberInfo getSubscriberInfo(Class subscriberClass) {
            SubscriberInfo info = SUBSCRIBER_INDEX.get(subscriberClass);
            if (info != null) {
                return info;
            } else {
                return null;
            }
        }
    }
    
  3. 添加索引到EventBus默认的单例中

    EventBus.builder().addIndex(new MyEventBusIndex()).installDefaultEventBus();
    

参考 ###

http://www.cnblogs.com/whoislcj/p/5595714.html

http://blog.csdn.net/harvic880925/article/details/40787203

你可能感兴趣的:(android开发)