This chapter explains how to think in terms of dataflow when building Android features with RxJava: express inputs as streams, transform them into meaningful intermediate signals, and combine those signals into clear, testable outputs. The core idea is to design a reactive graph—an explicit chain of transformations and combinations—so that UI behavior emerges from data dependencies rather than imperative control flow. By shifting the focus from handling callbacks to modeling state and relationships, you construct programs that are easier to reason about, observe, and evolve.
A central theme is the dual role of observables. Event observables represent transient events (for example, UI clicks) that are time-based and often carry little or no payload. Reactive variables, in contrast, represent evolving state and emit their full current value whenever it changes (and often immediately to new subscribers). The chapter shows how to interpret events into state—turning a stream of clicks into a Boolean “switch on/off” state—and discusses internal state, naming conventions to distinguish event observables, and diagramming practices that help communicate how streams relate without exposing implementation details.
The chapter’s case study builds a credit card validation form entirely as a reactive graph. Text inputs become observables; transformations derive card type via regex, verify the Luhn checksum, validate the expiration date format, and compute whether the CVC length matches the detected card type. Helpers built on combineLatest (such as AND and EQUALS) join these signals into a single isFormValid output that drives the Submit button, with doOnNext used for transparent logging and observeOn ensuring UI updates on the main thread. The result illustrates how RxJava code first constructs a dynamic graph in memory and then simply reacts to data, yielding traceable behavior, fewer “mystery states,” and a clearer separation between domain rules and UI concerns, while also noting practical UX refinements like deferring error indications during active editing.
FAQ
What are the two main roles an Observable can play in RxJava?Observables are typically used as either:
- Event observables: fire-and-forget event streams (for example, UI clicks). They’re time-based, often carry little/no payload (Observable<Void>/Observable<Object>), and don’t represent state.
- Reactive variables: streams that represent and emit the full state whenever it changes (for example, Observable<Boolean> isSwitchOn). Conceptually, new subscribers should get the current/latest state (commonly implemented with BehaviorSubject, replay(1), or startWith).How do I turn a stream of UI clicks into a boolean on/off state?You interpret events into state. A common pattern is to toggle with scan:
- clicksEventObservable.scan(false, (isOn, __) -> !isOn)
- Optionally start with an initial value and distinctUntilChanged to avoid redundant emissions.
The result is an Observable<Boolean> that represents isSwitchOn.What’s the difference between event observables and state observables in practice and diagrams?- Semantics: Event observables represent point-in-time occurrences; state observables represent the current value of something that changes over time.
- Data: Events may have no payload; state emissions carry the full state.
- Diagrams: It’s common to depict events differently (for example, dashed) and state with a solid line to emphasize “represents state.”
- Naming: Adding a suffix like EventObservable (for example, clicksEventObservable) makes intent explicit and nudges you to convert events into state early.Can I read an Observable’s latest value without subscribing?Ordinary Observables don’t expose a “current value.” If you need that behavior, use a subject like BehaviorSubject (which holds and exposes the latest value) or operators such as replay(1). In a reactive design you usually subscribe instead of pulling the value.What’s the Rx approach to building the credit card validation form?- Define inputs as Observables of user text for card number, expiration date, and CVC.
- Define the target output as isFormValidObservable (Observable<Boolean>).
- Break the problem into smaller validations (card type, checksum, CVC length, expiration format).
- Transform input streams with map and combine validations with combineLatest (often via small helpers like and/equals).
- Bind isFormValidObservable to the Submit button’s enabled state.How do I validate the expiration date (MM/YY) with RxJava?- Create an expirationDateObservable from the input field.
- Use map with a regex to produce Observable<Boolean>:
- expirationDateObservable.map(text -> text.matches("^\\d\\d/\\d\\d$"))
- Use that boolean stream as part of the overall isFormValidObservable.How is the credit card number validated (type and checksum)?- Card type: Map the number string to a CardType via regex rules, then map to a boolean that it’s not UNKNOWN.
- Checksum (Luhn): Map the string to its digits and apply the checksum function to get a boolean.
- Combine the two boolean streams (type valid AND checksum valid) with combineLatest (or a helper like ValidationUtils.and).How do I validate the CVC length based on the card type?- Reuse cardTypeObservable and map it to the required CVC length (for example, cardType.getCvcLength()).
- Map the CVC input to its length (String::length).
- Compare the two with combineLatest using equals logic (for example, a helper ValidationUtils.equals(requiredLength, actualLength)).What are ValidationUtils.and and ValidationUtils.equals, and why aren’t they in RxJava?They’re convenience helpers built on Observable.combineLatest:
- and(a, b) combines two (or more) boolean Observables with logical AND.
- equals(a, b) emits whether two Observables’ latest values are equal.
They’re simple, domain-specific wrappers to keep chains readable; the core operator is combineLatest.How can I log what flows through a chain without changing the data?Use side-effect operators:
- doOnNext(value -> Log.d(...))
- doOnError(error -> Log.e(...))
- doOnComplete(() -> Log.d(...))
They let you observe and log each emission, error, or completion without modifying the stream’s data.
pro $24.99 per month
access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!