Code Monkey home page Code Monkey logo

rxbus's Introduction

###RXBus Release Android Arsenal

#####RxJava V2: If you are looking for a version for RxJava V2, check out my RxBus2

What does it do?

  • it allows you to post events to a bus
  • it allows you to subscribe to special events whereever you want
  • it allows you to queue events until an activity is resumed (to make sure views are accessable for example)
  • it allows you to queue events as soon as activity is paused and emit events as soon soon as it is resumed
  • it's very lightweight

Gradle (via JitPack.io)

  1. add jitpack to your project's build.gradle:
repositories {
    maven { url "https://jitpack.io" }
}
  1. add the compile statement to your module's build.gradle:
dependencies {
    compile 'com.github.MFlisar:RXBus:1.0'
}

Migration

If you update from version <0.5 or version <0.9, follow this short migration guide: MIGRATION GUIDE

Usage

Content

#####Demo

Just check out the DemoActivity, it will show the base usage and the difference between the default and the queued RXBus

#####Simple usage

Use the RXBusBuilder to create subscriptions or simple observables. Just like following:

// Variant 1 - create a simple observable :
Observable<TestEvent> simpleObservable = RXBusBuilder.create(TestEvent.class).build();

// Variant 2 - subscribe with the BUILDER:
Subscription simpleSubscription = RXBusBuilder.create(TestEvent.class)
    .subscribe(new Action1<TestEvent>() {
        @Override
        public void call(TestEvent event) {
            // handle event...
            
            // event MUST have been send with either of following:
            // RXBus.get().sendEvent(new TestEvent()); => class bound bus usage
            // RXBus.get().sendEvent(new TestEvent(), R.id.observer_key_1, true); => key bound bus usage, with sendToDefaultBusAsWell = true, which will result in that all class bound observers (like this one) retrieve this event as well
        }
    });

#####Sending an event

// Send an event to the bus - all observers that observe this class WITHOUT a key will receive this event
RXBus.get().sendEvent(new TestEvent());
// Send an event to the bus - only observers that observe the class AND key will receive this event
RXBus.get().sendEvent(new TestEvent(), R.id.observer_key_1);
// Send an event to the bus - all observers that either observe the class or the class AND key will receive this event
RXBus.get().sendEvent(new TestEvent(), R.id.observer_key_1, true);

#####Advanced usage - QUEUING AND BINDING

You can use this library to subscribe to events and only get them when your activity is resumed, so that you can be sure views are available, for example. Just like following:

RXBusBuilder.create(TestEvent.class)
    // this enables the queuing mode! Passed object must implement IRXBusQueue interface, see the demo app for an example
    .withQueuing(rxBusQueue)
    .withOnNext(new Action1<TestEvent>() {
        @Override
        public void call(TestEvent s) {
            // activity IS resumed, you can safely update your UI for example
            
            // event MUST have been send with either of following:
            // RXBus.get().sendEvent(new TestEvent()); => class bound bus usage
            // RXBus.get().sendEvent(new TestEvent(), R.id.observer_key_1, true); => key bound bus usage, with sendToDefaultBusAsWell = true, which will result in that all class bound observers (like this one) retrieve this event as well
        }
    })
    .buildSubscription();

Additionally, you can bind the subscription to an object and afterwards call RXSubscriptionManager.unsubscribe(boundObject); to unsubcribe ANY subscription that was bound to boundObject just like following:

// boundObject... can be for example your activity
RXBusBuilder.create(TestEvent.class)
    // this enables the queuing mode! Passed object must implement IRXBusQueue interface, see the demo app for an example
    .withQueuing(rxBusQueue)
    .withBound(boundObject)
    .subscribe(new Action1<Object>() {
        @Override
        public void call(TestEvent s) {
            // activity IS resumed, you can safely update your UI for example

            // event MUST have been send with either of following:
            // RXBus.get().sendEvent(new TestEvent()); => class bound bus usage
            // RXBus.get().sendEvent(new TestEvent(), R.id.observer_key_1, true); => key bound bus usage, with sendToDefaultBusAsWell = true, which will result in that all class bound observers (like this one) retrieve this event as well
        }
    });
// call this for example in your activities onDestroy or whereever appropriate to unsubscribe ALL subscriptions at once that are bound to the boundOBject
RXSubscriptionManager.unsubscribe(boundObject);

#####Advanced usage - KEYS

You can use this library to subscribe to events of a typ and ONLY get them when it was send to the bus with a special key (and only when your activity is resumed, as this example shows via .withQueuing()), so that you can distinct event subscriptions of the same class based on a key (the key can be an Integer or a String). Just like following:

RXBusBuilder.create(TestEvent.class)
    // this enables the binding to the key
    .withKey(R.id.observer_key_1) // you can provide multiple keys as well
    .withQueuing(rxBusQueue)
    .withBound(boundObject)
    .subscribe(new Action1<String>() {
        @Override
        public void call(TestEvent event) {
            // activity IS resumed, you can safely update your UI for example

            // event MUST have been with either of those:
            // RXBus.get().sendEvent(new TestEvent(), R.id.observer_key_1); => key bound bus usage, class bound observers WON't retrieve this event as well!
            // RXBus.get().sendEvent(new TestEvent(), R.id.observer_key_1, true); => key bound bus usage, with sendToDefaultBusAsWell = true, resulting in class bound observers WILL retrieve this event as well!
        }
    });

#####Advanced usage

You can pass in a Observable.Transformer to transform the observed event to whatever you want!

Observable.Transformer<TestEvent, TestEventTransformed> transformer = new Observable.Transformer<TestEvent, TestEventTransformed>() {
    @Override
    public Observable<TestEventTransformed> call(Observable<TestEvent> observable) {
        return observable
                .map(new Func1<TestEvent, TestEventTransformed>() {
                    @Override
                    public TestEventTransformed call(TestEvent event) {
                        return event.transform();
                    }
                });
    }
};
RXBusBuilder.create(TestEvent.class)
    .withQueuing(rxBusQueue)
    .withBound(boundObject)
    .subscribe(new Action1<TestEventTransformed>() {
        @Override
        public void call(TestEventTransformed transformedEvent) {
        }
    }, transformer);

#####Helper class - RXSubscriptionManager

This class helps to bind subscriptions to objects and offers an easy way to unsubscribe all subscriptions that are bound to an object at once. You can simply use is directly with the RXBusBuilder via the RXBusBuilder.withBound(boundObject). This will automatically add the subscription to the RXSubscriptionManager when you call `RXBusBuilder.subscribe(...).

Directly

Subscription subscription = RXBusBuilder.create(...).build();
RXSubscriptionManager.addSubscription(activity, subscription);

RXBusBuilder

RXBusBuilder.create(...).withBound(activity);

Now you only have to make sure to unsubscribe again like following:

RXSubscriptionManager.unsubscribe(activity);

This will remove ANY subscription that is bound to activity and therefore this can be used in your activity's onDestroy method to make sure ALL subscriptions are unsubscribed at once and that you don't leak the activity.

Credits

The RxValve class is from this gist: https://gist.github.com/akarnokd/1c54e5a4f64f9b1e46bdcf62b4222f08

rxbus's People

Contributors

mflisar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

rxbus's Issues

RXSubscriptionManager

Why don't you use CompositeSubscription instead of HashSet<Subscription>? You only have to use "clear()" for unsubscribe.
Is there a reason?

Better API + clean up

  • Better API
  • Remove the IRXBusObservableProcessor

API should look like following:

// Subscription
RXBus.Builder.create(String.class)
		// all optional!!!
		.withQueuing(queuer)                // queuer implements IRXBusQueue
		.withBound(boundObject)             // subscription will be automatically bound to this object via RXSubscriptionManager!
		.withKey(R.id.custom_event_id_1)    // you may add multiple keys as well!
		.withMode(RXBusMode.Main)           // define a thread to emit events on
		.subscribe(new Action1<String>(){   // overwritten method with the same signatures as observable.subscribe!
			@Override
			public void call(String s) {
				// ...
			}
		});

subscribe will allow to pass in an Observer.Transformer to transform the events before they are emitted => this replaces the IRXBusObservableProcessor!

// Observable
Observable<String> observable = RXBus.Builder.create(String.class)
	.withQueuing(this)
	.withKey(R.id.custom_event_id_1) // you may add multiple keys as well!
	.build();

Proguard issue

How to solve this?
Warning:com.michaelflisar.rxbus.rx.RxValve$ValveSubscriber: can't find referenced class rx.internal.util.RxJavaPluginUtils

Strange behaviour...lately

I use the RXBus with String-keys. It was working fine.
But since yesterday I recognized that I run into key-events where I shouldn't.

I use this (an example):
RXBus.get().sendEvent("Account saved", BusKeysDef.SAVED_ACCOUNT);
and I also run into:
RXSubscriptionManager.addSubscription(this, RXBusBuilder.create(String.class).withBusMode(RXBusMode.Main) .withKey(BusKeysDef.CREATED_ACCOUNT) .withOnNext(s -> invalidateOptionsMenu()) .buildSubscription() );

Sorry for the formatting

Queuing not working

The demo activity currently does following:

  1. default event bus system works fine
  2. queued event bus system does not emit any items

The logging shows, that the resume observable for the RxValve works and gets called, but it does not trigger the main observable to emit queued items based on the RxValue operator.

Example log messages after starting app and pausing/resuming it:

D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {main} : main thread i=0 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {main} : main thread i=1 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {main} : main thread i=2 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {main} : main thread i=3 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {main} : main thread i=4 | isResumed=false
D/PauseAwareActivity: Thread startet...
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {Thread-279566} : some thread i=0 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {Thread-279566} : some thread i=1 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {Thread-279566} : some thread i=2 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {Thread-279566} : some thread i=3 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onCreate] {Thread-279566} : some thread i=4 | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=true): [onResume] {main} : BEFORE on resume | isResumed=true
D/PauseAwareActivity: onResumedChanged - resumed=true
D/PauseAwareActivity: onResumedChanged - resumed=true
D/PauseAwareActivity: ACTIVITY RESUMED
D/PauseAwareActivity: SIMPLE BUS (background=true): [onResume] {main} : AFTER on resume | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {main} : main thread i=0 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {main} : main thread i=1 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {main} : main thread i=2 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {main} : main thread i=3 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {main} : main thread i=4 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {Thread-279566} : some thread i=0 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {Thread-279566} : some thread i=1 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {Thread-279566} : some thread i=2 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {Thread-279566} : some thread i=3 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onCreate] {Thread-279566} : some thread i=4 | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onResume] {main} : BEFORE on resume | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onResume] {main} : AFTER on resume | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=true): [onPause] {main} : BEFORE on pause | isResumed=true
D/PauseAwareActivity: onResumedChanged - resumed=false
D/PauseAwareActivity: onResumedChanged - resumed=false
D/PauseAwareActivity: ACTIVITY PAUSED
D/PauseAwareActivity: SIMPLE BUS (background=true): [onPause] {main} : AFTER on pause | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=false): [onPause] {main} : BEFORE on pause | isResumed=false
D/PauseAwareActivity: SIMPLE BUS (background=false): [onPause] {main} : AFTER on pause | isResumed=false
D/PauseAwareActivity: onResumedChanged - resumed=true
D/PauseAwareActivity: onResumedChanged - resumed=true
D/PauseAwareActivity: ACTIVITY RESUMED
D/PauseAwareActivity: SIMPLE BUS (background=true): [onResume] {main} : BEFORE on resume | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=true): [onResume] {main} : AFTER on resume | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onResume] {main} : BEFORE on resume | isResumed=true
D/PauseAwareActivity: SIMPLE BUS (background=false): [onResume] {main} : AFTER on resume | isResumed=true

Problem

No ""QUEUED BUS" messeges in the log...

Sometimes events may be emited while activity is paused

it sometimes happens, that an event gets emited, while the activity is resumed due to the time difference between the valve checking the state and the forwarding to the real observer (in the meantime the state of the activity may have changed).

Workaround [IMPLEMENTED]:
Check the state when retrieving an event and resend the event to the bus => the activtiy is currently paused and you'll get the event when it's resumed again...

The RXBusBuilder is doing this... (mQueueSubscriptionSafetyCheckEnabled)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.