android-mvvm
android-mvvm copied to clipboard
Conductor integration, and Kotlin support
This is a rather large pull request, and I make this pull request to discuss whether the direction we're heading is good or not.
I created 3 modules: core, conductor, and kotlin. Each module can be published to bintray as a separate module, so the goal was to be able to use them independently.
The core module consists of the basic stuff that is needed to implement MVVM in Java: DataBinding adapters, BindingConversions, ReadOnlyField. Some classes are added here: ReadOnlyList and so on. For now I removed MvvmActivity, but that can be included here as well, or in a separate module. The core module has been migrated to RxJava2, I think we should drop support for RxJava1, or just create a separate branch, so that if anyone wants to use the current library with RxJava1 can do so.
The Kotlin module only contains two Kotlin files, and its goal is to provide Kotlin support, so a set of cool extension functions like Observable.asField(), and ObservableField.asObservable().
And finally, the last module is the Conductor module. Its goal is to build upon the Conductor Android framework, so that we can eliminate Activities and Fragments, and all our UI components can be written as Controllers. Also, Conductor retains Controllers on orientation change, so our ViewModel lifecycle can be 1:1 tied to the Controller lifecycle. This way, we don't lose any data on orientation change. Also, the ViewModel now can be aware of the Controller's lifecycle.
Consider the following code:
class LoginViewModel @Inject constructor(userService: UserService,
loginNavigator: LoginNavigator,
messageHelper: MessageHelper,
lp: ControllerLifecycleProvider) : ViewModel
val email = ObservableField<String>("")
val password = ObservableField<String>("")
val loginTap = PublishSubject.create<Any>()
private val loginResult = loginTap
.flatMapFirst(userService.login(email.get(), password.get()))
.share()
.attachToLifecycle(lp, ControllerEvent.ATTACH, ControllerEvent.DETACH)
init {
loginResult.subscribeBy(onNext = {
loginNavigator.navigateToMain()
})
}
So as you can see, the loginResult observable will be subscribed to when the Controller's attach event happens, and unsubscribed (completed) when the detach event happens.
What do you think? :)
Also, in reference to the LoginViewModel code:
As subscription completes after detach, that would dispose all subscriptions. So, how do they get reattached on attach?