Skip to content

Migration 4.x.x → 5.x.x

Etienne Lenhart edited this page Jun 10, 2020 · 3 revisions

Why the change to a Redux-like approach?

While the simple approach with putting all actions in the form of methods and state updates into a single ViewModel is easier to implement and grasp, I noticed some problems when using it in middle to larger scale projects. Since everything is packed inside a ViewModel class, testing becomes increasingly complicated the more functionality and dependencies are being added. Furthermore, I experienced some race conditions when using updateState from inside multiple asynchronous tasks. In general a lot of implementation details were left to the user which leads to more brittle and inconsistent code. By using a more opinionated approach Eiffel 5 is able to do a lot more work for you.

While some major refactoring of the way updateState works might be able to resolve some of these issues, I ultimately decided to go for a more complete package with vastly improved testability, built-in support for Kotlin Coroutines, Kotlin Flow and LiveData sources. The new EiffelViewModel mechanic does a lot more under the hood to manage the lifecycle and cancellation of commands, state restoration after process death and sequential updates to the state for you. This also allows for an extensive debug mode to help with UI debugging.

That's not to say that the simpler approach is obsolete. I'm currently of the opinion that the recent additions to AndroidX libraries, especially the ones targeting Coroutines integration, allow the implementation of the simpler state handling from Eiffel 4 without any third-party libraries. If you'd still like to go for a similar approach with a more sophisticated implementation and don't shy away from using RxJava, definitely check out MvRx from Airbnb.

Migration process

Since Eiffel 5 introduces a completely new concept, migration will be pretty complex and time-consuming. Almost all new functionality has been added in separate files and classes, while deprecating Eiffel 4 features. For now, this allows you to gradually switch to the new approach. Deprecated functionality won't be removed until the next major version.

Despite the different approach, for most of the previous concepts there's an equivalent in Eiffel 5:

4.x Concept 5.x Equivalent Notes
ViewState State Apart from the additional save and restore functions used for restoration after process kills, these are the same.
StateViewModel method Action Before, options to update state were exposed as methods on the ViewModel. Now, those are clearly defined as subclasses of an Action sealed class.
Side-effect in StateViewModel method Interception Implementation of business logic and other dependency calls and asynchronous handling were previously left to the user. Interceptions now provide out of the box support for Coroutines, Flow, LiveData and common architecture tasks with built-in custom Interceptions.
updateState call Update case Previously scattered calls to update state can now be formalized in a central Update instance as cases in a when expression.
BindingState BindableState BindableState is basically a more capable version of BindingState with support for adapting multiple states per bindable property.

Hopefully this information was helpful and gives you a good overview of how to migrate your existing implementation to the new, more robust approach of Eiffel 5.

Any questions or feedback? Simply tweet about it. Tweet

Clone this wiki locally