Skip to content

Instantly share code, notes, and snippets.

@vaughandroid
Last active September 22, 2017 22:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vaughandroid/1feaf1eb79552cdd93e70cfdee40710f to your computer and use it in GitHub Desktop.
Save vaughandroid/1feaf1eb79552cdd93e70cfdee40710f to your computer and use it in GitHub Desktop.
Experimenting with Rx architecture
class Wiring {
private final Observable<ViewModel> viewModelObservable;
Wiring(View view, ActionDispatcher actionDispatcher, Service service, ViewModelScanner viewModelScanner) {
viewModelObservable = view.uiEventObservable()
.compose(actionDispatcher.uiEventToAction())
.compose(service.actionToResult())
.compose(viewModelScanner.resultToViewModel());
}
public Observable<ViewModel> viewModelObservable() {
return viewModelObservable;
}
}
interface View {
Observable<UiEvent> uiEventObservable();
}
class ActionDispatcher {
ObservableTransformer<UiEvent, Action> uiEventToAction() {
ObservableTransformer<TextUpdated, Action> textUpdatedToAction =
events -> events
.flatMap(textUpdated -> Observable.just(new GetAutocomplete(textUpdated.text)));
ObservableTransformer<SubmitClicked, Action> submitClickedToAction =
events -> events
.flatMap(submitClicked -> Observable.just(new Submit(), new SendAnalytics("submit")));
return events -> events
.publish(shared -> Observable.merge(
shared.ofType(TextUpdated.class).compose(textUpdatedToAction),
shared.ofType(SubmitClicked.class).compose(submitClickedToAction)
));
}
}
class Service {
private final AutocompleteService autocompleteService;
private final SubmitService submitService;
public Service(AutocompleteService autocompleteService, SubmitService submitService) {
this.autocompleteService = autocompleteService;
this.submitService = submitService;
}
ObservableTransformer<Action, Result> actionToResult() {
return events -> events
.publish(shared -> Observable.merge(
shared.ofType(GetAutocomplete.class).compose(autocompleteService.transformer()),
shared.ofType(Submit.class).compose(submitService.transformer())
));
}
}
class SubmitService {
ObservableTransformer<Submit, SubmitResult> transformer() {
return events -> events
.flatMap(submit -> {
return Observable.just(SubmitResult.IN_FLIGHT, SubmitResult.SUCCESS);
});
}
}
class AutocompleteService {
ObservableTransformer<GetAutocomplete, AutoCompleteResult> transformer() {
return events -> events
.flatMap(getAutocomplete -> {
String[] results = new String[3];
results[0] = getAutocomplete.text + "a";
results[1] = getAutocomplete.text + "b";
results[2] = getAutocomplete.text + "c";
return Observable.just(
AutoCompleteResult.IN_FLIGHT,
AutoCompleteResult.success(results)
);
});
}
}
class ViewModelScanner {
ObservableTransformer<Result, ViewModel> resultToViewModel() {
return events -> events
.scan(ViewModel.initial(), (viewModel, result) -> {
viewModel = viewModel.copy();
viewModel.isLoading = (result == AutoCompleteResult.IN_FLIGHT
|| result == SubmitResult.IN_FLIGHT);
viewModel.submitButtonClickable = result != SubmitResult.IN_FLIGHT;
if (result == AutoCompleteResult.ERROR ||
result == SubmitResult.ERROR) {
viewModel.autocompleteOptions = null;
viewModel.text = "ERROR!";
} else if (result instanceof AutocompleteSuccessResult) {
viewModel.autocompleteOptions = ((AutocompleteSuccessResult) result).autocompletes;
} else if (result == SubmitResult.SUCCESS) {
viewModel.text = "SUCCESS!";
}
return viewModel;
})
.cache();
}
}
abstract class UiEvent {
static class TextUpdated extends UiEvent {
final String text;
TextUpdated(String text) {
this.text = text;
}
}
static class SubmitClicked extends UiEvent {
}
}
class ViewModel {
public static ViewModel initial() {
return new ViewModel();
}
String text;
String[] autocompleteOptions;
boolean submitButtonClickable = true;
boolean isLoading;
ViewModel copy() {
ViewModel result = new ViewModel();
result.text = text;
result.autocompleteOptions = autocompleteOptions;
result.submitButtonClickable = submitButtonClickable;
result.isLoading = isLoading;
return result;
}
}
abstract class Action {
static class GetAutocomplete extends Action {
final String text;
GetAutocomplete(String text) {
this.text = text;
}
}
static class Submit extends Action {
}
static class SendAnalytics extends Action {
final String event;
SendAnalytics(String event) {
this.event = event;
}
}
}
abstract class Result {
static class AutoCompleteResult extends Result {
public static final AutoCompleteResult IN_FLIGHT = new AutoCompleteResult();
public static final AutoCompleteResult ERROR = new AutoCompleteResult();
public static AutocompleteSuccessResult success(String... autocompletes) {
return new AutocompleteSuccessResult(autocompletes);
}
static class AutocompleteSuccessResult extends AutoCompleteResult {
final String[] autocompletes;
AutocompleteSuccessResult(String[] autocompletes) {
this.autocompletes = autocompletes;
}
}
}
static class SubmitResult extends Result {
public static final SubmitResult IN_FLIGHT = new SubmitResult();
public static final SubmitResult SUCCESS = new SubmitResult();
public static final SubmitResult ERROR = new SubmitResult();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment