事件总线框架

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

原理

观察者模式。

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;
}
}
  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();
}
});
}

重点就是这句:

// 在任何地方调用下面的方法,即可动态全局实现壁纸设置功能
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,值得学习使用。

Android学习系列(43)--使用事件总线框架EventBus和Otto的更多相关文章

  1. Android学习系列(23)--App主界面实现

    在上篇文章<Android学习系列(22)--App主界面比较>中我们浅略的分析了几个主界面布局,选了一个最大众化的经典布局.今天我们就这个经典布局,用代码具体的实现它. 1.预览图先看下 ...

  2. Android学习系列(17)--App列表之圆角ListView(续)

    http://www.cnblogs.com/qianxudetianxia/archive/2011/09/19/2068760.html   本来这篇文章想并到上篇Android学习系列(16)- ...

  3. Android学习系列--App列表之拖拽ListView(上)

    研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨.      鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. 一 ...

  4. Android学习系列(7)--App轮询服务器消息

    这篇文章是android开发人员的必备知识. 1.轮询服务器     一般的应用,定时通知消息可以采用轮询的方法从服务器拿取消息,当然实时消息通知的话,建议采用推送服务.    其中需要注意轮询的频率 ...

  5. Android学习系列(15)--App列表之游标ListView(索引ListView)

    游标ListView,提供索引标签,使用户能够快速定位列表项.      也可以叫索引ListView,有的人称也为Tweaked ListView,可能更形象些吧.      一看图啥都懂了: 1. ...

  6. [置顶] Android学习系列-Android中解析xml(7)

    Android学习系列-Android中解析xml(7) 一,概述 1,一个是DOM,它是生成一个树,有了树以后你搜索.查找都可以做. 2,另一种是基于流的,就是解析器从头到尾解析一遍xml文件.   ...

  7. Android开发事件总线之EventBus运用和框架原理深入理解

    [Android]事件总线之EventBus的使用背景 在我们的android项目开发过程中,经常会有各个组件如activity,fragment和service之间,各个线程之间的通信需求:项目中用 ...

  8. Otto事件总线框架的使用

    Otto是一个在Android中的事件总线框架,它是square的一个开源框架,具体介绍点击这里,项目下载点击这里 为什么要使用Otto事件总线: 通常来说在Android中: 1.Activity与 ...

  9. Android学习系列(11)--App列表之拖拽ListView(下)

    接着上篇Android学习系列(10)--App列表之拖拽ListView(上)我们继续实现ListView的拖拽效果. 7.重写onTouchEvent()方法.     在这个方法中我们主要是处理 ...

随机推荐

  1. SprignMVC+myBatis整合

    转载自:http://lydia-fly.iteye.com/blog/2153076 学习本节内容请先看"MyBatis的基本应用".地址:http://lydia-fly.it ...

  2. spring mvc配置完后实现下载功能

    实现是前台: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEn ...

  3. 【leetcode】Regular Expression Matching (hard) ★

    Implement regular expression matching with support for '.' and '*'. '.' Matches any single character ...

  4. C#实现把指定文件夹下的所有文件复制到指定路径下以及修改指定文件的后缀名

    1.实现把指定文件夹下的所有文件复制到指定路径下 public static void copyFiles(string path) { DirectoryInfo dir = new Directo ...

  5. October 4th 2016 Week 41st Tuesday

    Patience! The windmill never strays in search of the wind. 耐心等待!风车从不跑去找风. Sometimes we need to be pa ...

  6. main方法并发测试

    public static void main(String[] args) throws Exception{ RequestModel r = new RequestModel(); r.setT ...

  7. Android ArrayAdapter使用

    1. 可以直接使用getContext()获取Context对象 2. 可以在构造方法中传入context, 数据对象的列表, super(context, 0, object);完成Adapter的 ...

  8. 关于ActionContext.getContext()的用法心得

    转: 为了避免与Servlet API耦合在一起,方便Action类做单元测试,Struts 2对HttpServletRequest.HttpSession和ServletContext进行了封装, ...

  9. Sphinx的介绍和原理探索

    What/Sphinx是什么 定义 Sphinx是一个全文检索引擎. 特性 索引和性能优异 易于集成SQL和XML数据源,并可使用SphinxAPI.SphinxQL或者SphinxSE搜索接口 易于 ...

  10. python中的Iterable, Iterator,生成器概念

    https://nychent.github.io/articles/2016-05/about-generator.cn 这个深刻 谈起Generator, 与之相关的的概念有 - {list, s ...