Rxbus

a event bus trigger by code, constrained by thread, and avoid creating event class

Project Preface

When I found I have to create a class as the distinction between events for, when I found the event bus which we are using is not based on annotations, when I found some engineers did not have a very good cognitive about the event callback in which thread, when I found that after the introduction of rxjava/rxandroid library, someone still do not know how to use and expect event bus way, I decided to do it, then the rxbus which belong to me was born.

At the beginning of the project, I use the rxjava/rxandroid library to implement the event bus model, which is presented by the master branch. but later, because of a failure to repair bug, I have to use the most simple way to achieve a robust library, to ensure its high availability, so the version of the Maven central repository can be seen in the justbus branch.

Because of the API is valuable, so the interface of these two branches can be preserved and compatible. As for the master branch of bug, it also wants to be corrected, if you are a warm-hearted guy.

Samples

The English version of the sample will be provided in the follow-up. At present, you can also refer to the test code or the sample code in the Chinese version(see below). you know that, the code is the same!

中文版示例 ( The Chinese Version Of The Sample )

event bus模型介绍 org.rxbus.Rxbus类是个单例, 很容易看出来, 你只需Rxbus.singleInstance即可获得它的实例, 一般还需要经历以下步骤:


示例和规则解释

下面我们通过一个例子来说明一些规则, 那样你会更清楚怎么使用, 但这个例子我可不希望你用在实战上. 假设你有两个银行账户, 你的财务经理不知道为什么, 就是不定期的给你预先打一些差旅费, 而且忽然间银行柜员每月将等额年金打到你的PayPal账户, 偶尔你的朋友也会把钱存错在你的PayPal账户里, 你希望到账时收到一个通知, 假设你的妻子不放心你, 也想知道打款情况, 而你有些私房钱不希望她知道, 就是那个渣打银行账户. 我们通过代码来模拟这种欣欣向荣的场景:

// 订阅方法所在的类, 即事件接收类, 不仅可以是公开类, 还可以是final类, 非公开类, 内部类
public class You {
    public static final int Constant_paypal = "paypal".hashCode();
    public static final int Constant_SCBank = "StandardChartered".hashCode();
    public static final int Constant_Citibank = "Citibank".hashCode();

    // 使用code区分事件, 而不是参数类型

    @Subscribe(code = Constant_paypal, scheduler = Subscribe.SCHEDULER_CURRENT_THREAD /* 调用者当前线程中回调此方法, 如果你想同步回调 */ )
    public void moneyFromPaypal(String name, int amounts) { // 方法参数个数不限, 只要投递事件时参数能对应上
        System.out.println("friend named " + name + " pay $" + amounts + " on thread " + Thread.currentThread().getId() + " for " + getClass().getSimpleName());
    }

    @Subscribe(code = Constant_paypal, scheduler = Subscribe.SCHEDULER_CURRENT_THREAD)
    public void moneyFromPaypalQuota() { // 一个类中可以有多个方法订阅同一个事件code, 它们都将得到回调
         System.out.println("Receive annuity $" + amounts + " on thread " + Thread.currentThread().getId() + " for " + getClass().getSimpleName());
    }

    @Subscribe(code = Constant_SCBank, scheduler = Subscribe.SCHEDULER_CURRENT_THREAD)
    private void moneyFromStandardCharteredBank(int amounts) { // 订阅方法可以是私有方法
        System.out.println("StandardCharteredBank pay $" + amounts + " on thread " + Thread.currentThread().getId() + " for " + getClass().getSimpleName());
    }

    @Subscribe(code = Constant_Citibank, scheduler = Subscribe.SCHEDULER_IO_POOL_THREAD /* io线程池里回调这个方法 */ )
    public static void moneyFromCitibank(int amounts) { // 可以是静态方法, 当然到时需要注册的是此类类对象
        System.out.println("Citibank pay $" + amounts + " on thread " + Thread.currentThread().getId() + " for " + getClass().getSimpleName());
    }
}

// 此时她将可以收到除moneyFromStandardCharteredBank以外的通知, 尽管里面没有声明方法, 但继承了啊~
class YourWife extends You {
}

然后假设财务经理, 银行职员, 你的朋友长这个样子:

class FinanceManager {
    private static final Random rand = new Random();
    public static void payMoney(int amounts) {
         if (rand.nextBoolean()) {
            Rxbus.singleInstance.postAsync(You.Constant_Citibank, amounts);
         } else {
            Rxbus.singleInstance.postAsync(You.Constant_SCBank, amounts);
         }
    }
}
class BankOfficial {
    public static void payMoney() {
         Rxbus.singleInstance.postSync(You.Constant_paypal, 20);
    }
}
class YourFriend {
    private String name;
    public YourFriend(String name) {
         this.name = name;
    }
    public void payMoney(int amounts) {
         Rxbus.singleInstance.postAsync(You.Constant_paypal, name, 20);
    }
}

需要注意的是:

现在我们来测试一下:

public Test {
    public static void main(String[] args) {
        You you = new You();
        YourWife wife = new YourWife();
        Rxbus.singleInstance.registerSync(you); // 当用完以后, 可以使用unregisterSync取消订阅
        Rxbus.singleInstance.registerSync(wife); // 测试子类回调
        Rxbus.singleInstance.registerSync(You.class); // 为了接收静态方法回调
        // 可以参考日志
        FinanceManager.payMoney(300); // 注意在哪个线程得到的回调
        BankOfficial.payMoney();
        YourFriend zhangsan = new YourFriend("zhangsan"), lisi = new YourFriend("lisi");
        zhangsan.payMoney(20000);
        lisi.payMoney(5);
    }
}

最后需要嘚啵两句, 默认scheduler有:

枚举值 描述
SCHEDULER_CURRENT_THREAD 调用者当前线程中回调
SCHEDULER_NEW_THREAD 新建一个线程回调
SCHEDULER_IO_POOL_THREAD IO线程池(如未使用此值, 线程池不会被创建)中回调, 一般使用无线程池大小的cache线程池
SCHEDULER_COMPUTE_POOL_THREAD 计算线程池(如未使用此值, 线程池不会被创建)中回调, 一般使用固定大小的线程池(比如cpu核心数 + 1)

那么如何在自定义线程中回调呢? Android中有个主线程的概念, 以此为例, 说明一下如何绑定自定义线程:

// 注册
RxBus.singleInstance.addSchedulerWithId(SchedulerIdCenter.MAIN, AndroidSchedulers.mainThread());
...
// 使用
@Subscribe(code=108494, scheduler= SchedulerIdCenter.MAIN)
void yourMethod(...) {

即通过addSchedulerWithId和removeSchedulerWithId来实现自定义线程的绑定和解绑, 对于addSchedulerWithId, 它接收两个参数:

备注: 目前没有单方法支持多code的计划, 即你不可能看到@Subscribe(code={1,8,9}, scheduler=...)...的情况, 取而代之, 你可以让方法接收一个参数来进一步分流, 比如触摸事件分为单击, 双击, 你既可以分配两个code, 然后对应两个不同的回调方法, 也可以分配一个code, 然后对应一个带参回调, 见下面代码: 第一种:

@Subscribe(code=SINGLE_CLICK_INT, scheduler=...)
void method() {...}
@Subscribe(code=DOUBLE_CLICK_INT, scheduler=...)
void method() {...}

第二种:

@Subscribe(code=CLICK_INT, scheduler=...)
void method(int type) {
    switch(type) {
        case SINGLE_CLICK:
        case DOUBLE_CLICK:
    }
}

Gradle

compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.1.6'
compile ('com.github.johnlee175:rxbus:1.0.2') {
    exclude group:'io.reactivex', module:'rxandroid'
    exclude group:'io.reactivex', module:'rxjava'
}

License

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache license, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the license for the specific language governing permissions and
limitations under the license.