Android学习系列(43)--使用事件总线框架EventBus和Otto

事件总线框架

针对事件提供统一订阅,发布以达到组件间通讯的解决方案。java

原理

观察者模式。android

EventBus和Otto

先看EventBus的官方定义:git

Android optimized event bus that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality.

再看Otto官方定义:github

Otto is an event bus designed to decouple different parts of your application while still allowing them to communicate efficiently.

总之,简化android应用内组件通讯。设计模式

对比BroadcastReceiver

在工做上,我在两个场景下分别使用过Otto和EventBus,一个是下载管理器通知各个相关的Activity当前的进度,一个是设置应用壁纸。
单从使用上看,EventBus > Otto > BroadcastReceiver(固然BroadcastReceiver做为系统内置组件,有一些前二者没有的功能).
EventBus最简洁,Otto最符合Guava EventBus的设计思路, BroadcastReceiver最难使用。
我我的的第一选择是EventBus。app

实例:“设置壁纸”

两大的框架的基本使用都很是简单:
EventBus的基本使用官方参考:https://github.com/greenrobot/EventBus
Otto的基本使用官方参考:http://square.github.io/otto/框架

EventBus实现篇

EventBus规定onEvent方法固定做为订阅者接受事件的方法,应该是参考了“约定优于配置”思想。ide

  1. 定义EventModel,做为组件间通讯传递数据的载体
public class WallpaperEvent {

    private Drawable wallpaper;

    public WallpaperEvent(Drawable wallpaper) {
        this.wallpaper = wallpaper;
    }

    public Drawable getWallpaper() {
        return wallpaper;
    }

    public void setWallpaper(Drawable wallpaper) {
        this.wallpaper = wallpaper;
    }
}
  1. 定义订阅者,最重要的是onEvent方法
public class BaseActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        EventBus.getDefault().register(this);
        initWallpaper();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

    public void onEvent(WallpaperEvent wallpaperEvent) {
        // AppConfig.sWallpaperDrawable as a global static var
        AppConfig.sWallpaperDrawable = wallpaperEvent.getWallpaper();
        initWallpaper();
    }

    private void initWallpaper() {
        // support custom setting the wallpaper
        // 根据AppConfig.sWallpaperDrawable,默认值等设置当前Activity的背景壁纸
        // ...
    }
}
  1. 经过post()方法在任何地方发布消息(壁纸,准确的说是WallpaperEvent)给全部的BaseActivity子类,举个例子:
private void downloadWallpapper(String src) {
        ImageLoader.getInstance().loadImage(src, new SimpleImageLoadingListener() {
            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {

                BitmapDrawable wallpaper = new BitmapDrawable(loadedImage);
                // presist the image url for cache
                saveWallpaper(imageUri);

                // notify all base activity to update wallpaper
                EventBus.getDefault().post(new WallpaperEvent(wallpaper));


                Toast.makeText(WallpapeEventBusrActivity.this,
                        R.string.download_wallpaper_success,
                        Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
                Toast.makeText(WallpaperActivity.this,
                        R.string.download_wallpaper_fail,
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

重点就是这句:post

// 在任何地方调用下面的方法,便可动态全局实现壁纸设置功能
EventBus.getDefault().post(new WallpaperEvent(wallpaper));

Otto实现篇

这里要注意几点点:
(1)Otto使用注解定义订阅/发布者的角色,@Subscribe为订阅者,@Produce为发布者,方法名称就能够自定义了。
(2)Otto为了性能,代码意图清晰,@Subscribe,@Produce方法必须定义在直接的做用类上,而不能定义在基类而被继承。
(3)和EventBus不一样的是,发布者也须要register和unregister,而EventBus的发布者是不须要的。性能

  1. 定义EventModel,做为组件间通讯传递数据的载体
public class WallpaperEvent {

    private Drawable wallpaper;

    public WallpaperEvent(Drawable wallpaper) {
        this.wallpaper = wallpaper;
    }

    public Drawable getWallpaper() {
        return wallpaper;
    }

    public void setWallpaper(Drawable wallpaper) {
        this.wallpaper = wallpaper;
    }
}
  1. 避免浪费,相对于EventBus.getDefault(), Otto须要本身实现单例。
public class AppConfig {

    private static final Bus BUS = new Bus();

    public static Bus getInstance() {
        return BUS;
    }
}
  1. 定义订阅者,在接受事件的方法加上修饰符@Subscribe
public class BaseActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        AppConfig.getBusInstance().register(this);
        initWallpaper();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        AppConfig.getBusInstance().unregister(this);
    }

    public void onOttoEvent(WallpaperEvent wallpaperEvent) {
        AppConfig.sWallpaperDrawable = wallpaperEvent.getWallpaper();
        initWallpaper();
    }

    private void initWallpaper() {
        // support custom setting the wallpaper
        // 根据AppConfig.sWallpaperDrawable,默认值等设置当前Activity的背景壁纸
        // ...
    }
}
  1. 定义发布者,经过post()方法在任何地方发布消息了
public class WallpaperActivity extends BaseActivity {

    private Drawable wallpaperDrawable;

    //这里同时也要更新本身壁纸,因此显示定义@Subscribe的方法
    @Subscribe
    public void onWallpaperUpdate(WallpaperEvent wallpaperEvent) {
        super.onWallpaperUpdate(wallpaperEvent);
    }

    @Produce
    public WallpaperEvent publishWallPaper() {
        return new WallpaperEvent(wallpaperDrawable);
    }

    private void downloadWallpapper(String src) {
        //...
        //通知全部@Subscribe匹配WallpaperEvent参数的方法执行
        AppConfig.getBusInstance().post(publishWallPaper());
        //...
    }
}

小结

  1. 使用设计模式的思想解决问题,这才是设计模式的真正价值。
  2. 这两个android事件总线框架提供了一种更灵活更强大而又更加完美解耦的解决方案,在不少场合,从开发效率,执行性能和设计思路上都要优于BroadcastReceiver,值得学习使用。
相关文章
相关标签/搜索