Grox helps to maintain the state of Java / Android apps.
Clone or download
Alin Turcu
Latest commit 330a0ad Jul 5, 2018
Permalink
Failed to load latest commit information.
.buildscript Take TP config for travis (#3) Jun 20, 2017
assets Add logo Nov 1, 2017
config Move Rx classes under version namespace to prevent collisions May 25, 2018
gradle Move Rx classes under version namespace to prevent collisions May 25, 2018
grox-commands-rx Generic version of Command Mar 16, 2018
grox-commands-rx2 Generic version of Command Mar 16, 2018
grox-core-rx Move Rx classes under version namespace to prevent collisions May 25, 2018
grox-core-rx2 Move Rx classes under version namespace to prevent collisions May 25, 2018
grox-core Setup code coverage #2 Dec 16, 2017
grox-sample-rx Merge pull request #40 from wongcain/generic_commands Jul 4, 2018
grox-sample-rx2 Merge pull request #40 from wongcain/generic_commands Jul 4, 2018
grox-sample Move Rx classes under version namespace to prevent collisions May 25, 2018
.gitignore Initial commit Jun 16, 2017
.travis.yml updating travis yml with new tools version Jun 4, 2018
CHANGELOG.md Prepare for release 1.1.2 Jul 4, 2018
LICENSE issue-7: add full license Jun 21, 2017
README.md Fix typo Jan 11, 2018
RELEASING.md Prepare for release 1.1.0 Sep 7, 2017
build.gradle Move Rx classes under version namespace to prevent collisions May 25, 2018
gradle.properties Prepare next development version. Jul 5, 2018
gradlew Initial commit Jun 16, 2017
gradlew.bat Initial commit Jun 16, 2017
settings.gradle Add RxJava2 support. Created grox-core-rx2, grox-commands-rx2 and a n… Nov 8, 2017

README.md

Grox

Grox helps to maintain the state of Java / Android apps.






Understanding Grox

Grox Overview

Video

Grox video

We have a nice video to explain how the Grox sample app works.

Wiki

Visit the Grox wiki

Grox in a nutshell

Grox provides developers with the basic bricks to:

  • create a state of a UI / Application
  • perform pure changes on this state,
  • be notified of state changes (i.e. to update the UI)
  • perform other "side-effects" operations (network calls, manipulating files, etc.)
  • log, persist, create an history of states and state changes

Basic Usage

Very simple example:

//create a store with an initial state
Store<String> store = new Store<>("Hello");
//when the store's state changes, update your UI
states(store).subscribe(System.out::println);
//start dispatching actions to your store...
store.dispatch(oldState -> oldState + " Grox");

A command example

public class RefreshResultCommand implements Command {
 @Override
  public Observable<Action> actions() {
    return getResultFromServer() //via retrofit
        .subscribeOn(io())
        .map(ChangeResultAction::new) //convert all your results into actions
        .cast(Action.class)
        .onErrorReturn(ErrorAction::new) //including errors
        .startWith(fromCallable(RefreshAction::new)); //and progress
  }
}

//then use your command via Rx + RxBinding
subscriptions.add(
        clicks(button)
            .map(click -> new RefreshResultCommand())
            .flatMap(Command::actions)
            .subscribe(store::dispatch));

Note that such a command should be unsubscribed from when the UI element (e.g. an activity) containing the button button will no longer be alive. Otherwise, the Rx chain would leak it.

However, if you preserve your store accross configuration changes (using ViewModels, Dependency Injection (Toothpick/Dagger), retained fragments, etc.), you can also execute commands independently of the lifecycle of the UI:

//then use your command via Rx + RxBinding
subscriptions.add(
        clicks(button)
            .subscribe(click -> new RefreshResultCommand()
                                .actions()
                                .subscribe(store::dispatch)));

In this case, only the outer chain needs to be unsubcribed from when the UI elements are not alive anymore, the inner chain will be preserved during rotation and udpate the store even during a configuration change (e.g. a rotation), and the UI will display the latest when connecting to the store when the rotation is complete. A fine grained management of resources would unsubscribe from the inner chain when the store is not alive anymore.

Browse Grox sample for more details.

Setup

    //note that Grox is also available without Rx dependencies
    implementation 'com.groupon.grox:grox-core-rx:x.y.z'
    //Grox commands artifacts do depend on Rx (1 or 2)
    implementation 'com.groupon.grox:grox-commands-rx:x.y.z'
    implementation 'com.groupon.grox:grox-commands-rx2:x.y.z'

Main features

The main features of Grox are:

  • unify state management. All parts of an app, all screens for instance, can use Grox to unify their handling of state.
  • allows time travel debugging, undo, redo, logging, etc. via middlewares.
  • simple API. Grox is inspired by Redux & Flux but offers a simpler approach.
  • easily integrated with Rx1 and 2. Note that it is also possible to use Grox without Rx.
  • Grox only relies on a few concepts: States, Actions, Stores, MiddleWare & Commands (detailed below).
  • facilitates using immutable states, but without enforcing it for more flexibility. You can use any solution for immutability (Auto-Value, Immutables, Kotlin, etc..) or not use immutability at all if you don't want to.
  • Grox can be used with the Android Arch components, or without them.

Links

Conferences, talks & articles

Credits

The following people have been active contributors to the first version of Grox:

  • Shaheen Ghiassy
  • Michael Ma
  • Matthijs Mullender
  • Turcu Alin
  • Samuel Guirado Navarro
  • Keith Smyth
  • Stephane Nicolas

Inspired by

Grox - Java library for state management, inspired by Flux, Redux, Cycle, and Rx Managed State.