事件总线框架

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

原理

观察者模式。

EventBus和Otto

先看EventBus的官方定义:

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

再看Otto官方定义:

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。

实例:“设置壁纸”

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

EventBus实现篇

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

  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;}}
  2. 定义订阅者,最重要的是onEvent方法

    public class BaseActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    EventBus.getDefault().register(this);    initWallpaper();}@Overrideprotected 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的背景壁纸    // ...}}
  3. 通过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();        }    });}

    重点就是这句:

    // 在任何地方调用下面的方法,即可动态全局实现壁纸设置功能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;}}
  2. 避免浪费,相对于EventBus.getDefault(), Otto需要自己实现单例。

    public class AppConfig {private static final Bus BUS = new Bus();public static Bus getInstance() {    return BUS;}}
  3. 定义订阅者,

    public class BaseActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    AppConfig.getBusInstance().register(this);    initWallpaper();}@Overrideprotected 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的背景壁纸    // ...}}
  4. 定义发布者,通过post()方法在任何地方发布消息了

    public class WallpaperActivity extends BaseActivity {private Drawable wallpaperDrawable;//这里同时也要更新自己壁纸,所以显示定义@Subscribe的方法@Subscribepublic void onWallpaperUpdate(WallpaperEvent wallpaperEvent) {    super.onWallpaperUpdate(wallpaperEvent);}@Producepublic WallpaperEvent publishWallPaper() {    return new WallpaperEvent(wallpaperDrawable);}private void downloadWallpapper(String src) {    //...    //通知所有@Subscribe匹配WallpaperEvent参数的方法执行    AppConfig.getBusInstance().post(publishWallPaper());    //...}}

小结

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

更多相关文章

  1. Android之旅十三 android中的数据传递方法
  2. 【Frida Hook 学习记录】Frida Hook Android(安卓)常用方法
  3. RemoteViews用法一:widget简单用法
  4. Android笔记——Day1 *Activity生命周期 *Activiity切换效果
  5. Android学习札记47:TextView显示Html类解析的网页和图片及自定义
  6. Android(安卓)Service 服务—— bindService与remoteService
  7. android 异步加载
  8. Android(安卓)数据持久化方式
  9. Android(安卓)View事件派发机制详解与源码分析

随机推荐

  1. 全面解析Linux 内核 3.10.x - 编译前的准
  2. Linux系统Oracle12.2 RAC集群实施维护_Or
  3. 【linux】Centos7 防火墙操作
  4. 鸟哥的Linux私房菜——基础学习篇(第三版)
  5. keepalived for linux(HA 高可用集群)
  6. Cerebro 一个跨平台的桌面快捷使用工具
  7. Linux Mint 17下Sublime插件Emmet的安装
  8. Linux内核源代码情景分析读书笔记(5)-关于
  9. thinkphp连接mysql数据库查询数据显示
  10. Linux多线程实践(一)线程基本概念和理论