NOTE: I’ve deprecated Flowless (and have abandoned using Flow) in favor of what I wrote based on that from scratch: Simple-Stack . So you should keep in mind that I am no longer using this, because Simple-Stack solves quirks that I didn’t like about Flow’s design. — — — — — — — — — — — — — — — — — — — — — — — — — This is a follow-up article to . Saying No To Fragments and Activities: Creating View-driven Applications with Flow While I claimed that that article will get to the point, it was more-so a comparison of how things are lately with (and ), . So one could argue that it did not get straight to the point, after all. Flow 1.0-alpha2 Flowless versus how things used to be with Flow 0.8 So let’s get to it, shall we? Flow: a backstack manager As , the primary task of Flow (and the instance itself) is to manage the . All it really cares about is the (essentially a ), and exposes operators that allow it. stated in a previous article Flow backstack History List<Object> manipulating Keys: representation of application state The primary difference using Flow compared to just Activities is that instead of having an , you have a History of “key” objects that are just general Parcelable objects with and that represent what view you’re supposed to be showing. implicit backstack created by a series of Intents that open a bunch of Activities hashCode() equals() (In fact, it doesn’t have to be a view, if you’re a heretic, you can even use Fragments with it. No, really; just use the newly added _FragmentManager.commitNow()_ , and don’t use _addToBackStack()_ , defer backstack manipulation to Flow instead. Theoretically, it should work, although I must admit I haven’t tried it yet.) A possible example key would be the following: But if you don’t like extracting values from annotations, then you can just use interfaces and method calls. It’s up to you! This allows simple initialization for what your application state should be. And it also allows you to easily set whatever view you want to test with instrumentation tests. You might be thinking, “wait, but this is a whole bunch of methods in the key, I thought this was going to make my life simpler?!” Actually, it does. Exactly because this kind of “behavior” that is encoded here in the key used to be thrown randomly into Fragments, that were manipulating the Toolbar title in the Activity directly. Here this is something you can globally do in your dispatcher implementation, and it’s set properly on back press too with minimal effort (in fact, it works out of the box). Custom Views, and listening to the lifecycle This is a -specific feature, partly piggybacking on top of the fragment in the original Flow. Flowless InternalLifecycleIntegration You generally need to know when your View is ready and its state is restored. You must also know when your View is killed, so that you can unsubscribe your subscriptions, or unregister from event buses. Previous Flow examples used to show and as the callbacks to be used, but that is actually unreliable. There are cases when is called, but is not. In that case, you do not receive any callback to , which means that you can lose your state! onAttachedToWindow onDetachedFromWindow onFinishInflate() onAttachedToWindow() onDetachedFromWindow() If you’re curious, this is most likely why the library exists. square/coordinators Instead, Flowless introduces the interface, which if you implement, then provides you the callbacks: and . FlowLifecycles.ViewLifecycleListener onViewRestored() onViewDestroyed() Additional lifecycle callbacks In other cases such as writing a , you might need to listen to permission results, or activity results. CameraView For and , you need to delegate these callbacks to the Dispatcher manually. onActivityResult onPermissionResult A possible base activity that hides this from you would be the following: Once the permission result delegation is added, the dispatcher forwards this event to the current active view. This way, you can handle any lifecycle event callback you need in your view. ServiceProvider: sharing services across the view hierarchy This is a new class in Flowless, its counterpart used to be .with its corresponding . The is pretty much just a that is stored inside Flow’s to preserve them across configuration change, very similar to Mortar which is essentially a . The initial key in this case of course is the itself, and not a “scope name” specified as a String. Flow.Services ServiceFactory ServiceProvider Map<Object, Map<String, Object>> InternalLifecycleIntegration Map<String, Map<String, Object>> Key The difference is that in the original Flow 1.0-alpha2, the were managed internally based on a reference count, based on interfaces such as or . This could cause problems even if you weren’t using it, which is what caused the crash that made me fork Flow and create Flowless in the first place. Flow.Services TreeKey MultiKey Instead, in Flowless, the expects you to set it up in the Dispatcher however you see fit. ServiceProvider Through , the allows you to obtain any service from your context, just like you can obtain Flow via . the magic of redefining [getSystemService()](https://github.com/Zhuinden/realm-book-example/commit/619546401dcade1fbc02001e8b12d71bfcec2952) ServiceProvider Flow.get(context) Sharing a Dagger2 component In the MVP example, this is how scoped components are provided down the view hierarchy. This allows us to obtain the Dagger2 component from any context — primarily within views of the custom view’s view hierarchy. Dispatcher: which determines what happens on state change The last and most important component of a Flow-based application is its Dispatcher implementation. This is what globally handles what should happen when you go from Key A to Key B. The most typical implementation would persist the state of the previous view, inflate the new view, restore state to the new view, remove the previous view, add the new view, and callback to signal completion. The following example also adds the Dagger2 component by and associate it with the given key, making the component accessible within the view hierarchy. DaggerService.TAG In the middle, you can see the Service being set up for the current key: the Dagger2 Component. This is basically where the “magic” happens. In this case, it’s 60 lines with comments, compared to the FragmentManager that is 2000 lines. I guess there’s a win there in simplicity. Conclusion Hopefully this helped understand how to use , and how to create a simple MVP-based (or maybe even MVVM-based with Data-Binding or RxJava!) application without using fragments or any kind of additional “arcane folklore” beyond an explicit backstack. Flowless The app is driven with just simple parcelable POJOs, and you write how to switch between the states only once. Simpler than either s or s. FragmentTransaction Intent The example cited multiple times during this article is available . Flow is primarily responsible for the way the layer works. here presentation