zoukankan      html  css  js  c++  java
  • Android学习系列(43)--使用事件总线框架EventBus和Otto

    事件总线框架

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

    原理

    观察者模式。

    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,值得学习使用。
  • 相关阅读:
    书列君荐书|《福尔摩斯探案大全集》.(英)阿瑟.柯南道尔.扫描版
    anaconda同时集成Python2 和 Python3
    python 使用sqlite,ConfigParser实例
    python 爬虫爬取历年双色球开奖信息
    关于python 爬虫遇到的反盗链
    CentOS7搭建Docker私有仓库----Docker
    Ansible + shell 实现部署fastdfs+nginx 实现图片服务器并提供动态缩放功能;
    python+fastdfs+nginx实现打包下载功能
    监控生产服务器内存使用前十
    python操作MySQL--实例
  • 原文地址:https://www.cnblogs.com/qianxudetianxia/p/4216949.html
Copyright © 2011-2022 走看看