AndroidEventBus带来组件交互和应用退出新方式

CSDN一篇关于AndroidEventBus的新用法总结真是让人耳目一新,既有关于activity交互的新玩法也有退出应用的新玩法。确实太酷了。
原文地址:http://www.csdn.net/article/2015-04-22/2824531/1

初见AndroidEventBus

使用AndroidEventBus简单概括只有三个步骤:

将对象注册到AndroidEventBus中;
使用@Subcriber标注订阅函数(只能有一个参数);
通过post函数发布事件。
接下来就是注册订阅对象,如代码3所示。

public class MainActivity extends Activity {  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        // 将对象注册到事件总线中, ****** 注意要在onDestory中进行注销 ****  
        EventBus.getDefault().register(this);  
    }  
    @Override  
    protected void onDestroy() {  
        super.onDestroy();  
        // ****** 不要忘了进行注销 ****  
        EventBus.getDefault().unregister(this);  
    }      
    // 代码省略  
} 
                        代码3

在onCreate中注册之后,MainActivity就可以添加订阅函数来接收消息了。需要注意的是在onDestory中需要将MainActivity从事件总线中注销。通过AndroidEventBus你可以去除Activity、Fragment、Service等组件的回调,减少了耦合,简化了代码。

事件订阅函数

事件订阅需要使用@Subscriber注解进行标识,且订阅函数的参数必须为一个。事件总线凭借参数类型和@Subscriber注解的tag值来标识订阅函数的唯一性。当用户发布事件时,总线库会根据事件类型和tag来查找符合要求的订阅函数,并且将这些订阅函数执行在对应的线程中。我们先来看看代码4的订阅函数示例。

public class MainActivity extends Activity {  
    // 代码省略   
    @Subcriber(tag = "csuicide")  
    private void csuicideMyself(String msg) {  
        // do sth  
        finish();  
    }  
    @Subcriber(mode = ThreadMode.MAIN)  
    private void toastMsgFromEvent(String msg) {  
        // do sth  
    }  
    @Subcriber(tag = "async", mode = ThreadMode.ASYNC)  
    private void executeAsync(final String msg) {  
       // do sth  
    }  
    // 代码省略  
}      
                         代码4

在代码4中,我们为MainActivity添加了以下三个订阅函数:

csuicideMyself:该订阅函数执行在主线程,接收事件的类型为String,tag为csuicide。当用户发布一个事件类型为String,且tag为csuicide的事件时将会触发该方法。
toastMsgFromEvent:该订阅函数也是执行在主线程,事件类型为String,且tag为默认。当用户发布一个事件类型为String,且tag为默认的事件时将会触发该方法。
executeAsync:该订阅函数也是执行在一个异步线程,事件类型为String,且tag为async。当用户发布一个事件类型为String,且tag为async的事件时将会触发该方法。
从上述的描述中我们可以知道,事件接收函数主要有两个约束:事件类型和tag(类似于Intent中的Action)。添加tag是因为在事件类型一样时,如果投递一个消息,那么单纯以事件类型(例如String)作为投递依据,那么多个参数为String的订阅函数将会被触发,这极大地降低了灵活性。

发布事件
参数1为事件类型,无tag:EventBus.getDefault().post(这是一个执行在异步线程的事件);参数2为tag,tag的类型为String,类似Intent的Action:EventBus.getDefault().post(这是一个执行在异步线程的事件:“async”)。

发布事件时可以构造任意类型的事件,如果没有tag则该参数可以省略。发布事件后,AndroidEventBus会根据事件类型和tag到已注册的订阅对象中查找符合要求的订阅函数,例如投递的第二个事件类型为String、tag为async,那么在MainActivity中符合要求的订阅函数就是:

@Subcriber(tag = "async", mode = ThreadMode.ASYNC)  
 private void executeAsync(final String msg) {  
   // do sth  
 }  

AndroidEventBus的ThreadMode

在上述代码中有一段代码是这样的:

@Subcriber(mode = ThreadMode.MAIN)  
 private void toastMsgFromEvent(String msg) {        
 }  

这个mode可是大有来头,它指定这个事件接收函数执行在哪个线程中。具体有如下三个选项:

ThreadMode.MAIN,事件接收函数执行在UI线程;
ThreadMode.POST,事件在哪个线程发布,接收函数就执行在哪个线程;
ThreadMode.ASYNC,事件执行在一个独立的异步线程中。
图1中,事件接收函数就执行在异步线程。通过这几个线程模型,我们就可以定制接收函数的执行线程。这样我们就可以使用AndroidEventBus做很多事了。比如发布一个事件,在这个事件接收函数中进行耗时操作;或下载图片、进行HTTP请求、I/O操作等,以及替换Thread、AsyncTask等组件。不过,AndroidEventBus的功能远不止于此,下面我们就看看如何进行更高端的操作。

这里写图片描述

图1 接收函数执行在异步线程中

/** 
 * 事件处理接口,处理事件的抽象 
 */  
public interface EventHandler {  
    /** 
     * 处理事件 
     * @param subscription 订阅对象 
     * @param event 待处理的事件 
     */  
    void handleEvent(Subscription subscription, Object event);  
}  
代码7

默认有DefaultEventHandler、UIThreadEventHandler、AsyncEventHandler三个实现:

DefaultEventHandler:事件在哪个线程发布,就将事件接收函数执行在哪个线程;
UIThreadEventHandler:将事件接收函数执行在UI线程;
AsyncEventHandler:将事件接收函数执行在异步线程。
下面我们以自定义异步事件处理器,也就是AsyncEventHandler,通过实现EventHandler接口,将事件处理函数执行在一个线程池中,从而实现图片下载的功能。如代码8所示。

public class ThreadPoolHandler implements EventHandler {  
    ExecutorService mExecutorService = Executors.newFixedThreadPool(3);  
    EventHandler mHandler = new DefaultEventHandler();  
    @Override  
    public void handleEvent(final Subscription subscription, final Object event) {  
        mExecutorService.submit(new Runnable() {  
            @Override  
            public void run() {  
                mHandler.handleEvent(subscription, event);  
            }  
        });  
    }  
}  
                        代码8

然后通过如下代码将ThreadPoolEventHandler注入到:

这里写图片描述

图2 图片下载中页面

这里写图片描述

图3 图片下载完成页面

EventBus中:

// 自定义的异步事件处理器,使用线程池
EventBus.getDefault().setAsyncEventHandler(new ThreadPoolHandler());
再在订阅对象中添加代码9所示的订阅方法 :

@Subcriber(tag = "download", mode = ThreadMode.ASYNC)  
private void downloadImage(final String imageUrl) {  
    HttpURLConnection urlConnection = null;  
    try {  
        final URL url = new URL(imageUrl);  
        urlConnection = (HttpURLConnection) url.openConnection();  
        final Bitmap bmp = BitmapFactory.decodeStream(urlConnection.getInputStream());           
        // 将Bitmap投递给ImageView之类的工作  
    } catch (IOException e) {  
    } finally {  
        if (urlConnection != null) {  
            urlConnection.disconnect();  
        }  
    }  
}  
                         代码9

最后,当需要下载图片时,通过post发布一个参数为String类型、tag为download的事件即可执行downloadImage函数,这个函数将执行在线程池中,我们的简易ImageLoader就这么实现了。图2、图3分别为图片下载中和图片下载完成的页面。

当然,由于AndroidEventBus的高度定制化,我们还可以通过AndroidEventBus来实现各种各样的功能,它到底还能怎么玩,我就不做过多的演示了,开发者可以充分发挥自己的聪明才智和想象力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值