針對事件提供統一訂閱,發佈以達到組件間通訊的解決方案。java
觀察者模式。android
先看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應用內組件通訊。設計模式
在工做上,我在兩個場景下分別使用過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規定onEvent方法固定做爲訂閱者接受事件的方法,應該是參考了「約定優於配置」思想。ide
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; } }
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的背景壁紙 // ... } }
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));
這裏要注意幾點點:
(1)Otto使用註解定義訂閱/發佈者的角色,@Subscribe爲訂閱者,@Produce爲發佈者,方法名稱就能夠自定義了。
(2)Otto爲了性能,代碼意圖清晰,@Subscribe,@Produce方法必須定義在直接的做用類上,而不能定義在基類而被繼承。
(3)和EventBus不一樣的是,發佈者也須要register和unregister,而EventBus的發佈者是不須要的。性能
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; } }
public class AppConfig { private static final Bus BUS = new Bus(); public static Bus getInstance() { return BUS; } }
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的背景壁紙 // ... } }
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()); //... } }