From ae03d3d4d2f45451378a212f404b395bde28b0ef Mon Sep 17 00:00:00 2001 From: Ruslan Davletshin Date: Sun, 16 Feb 2020 19:49:35 +0300 Subject: [PATCH 1/6] add disposable view model abstraction --- .../presentation/base/DisposableViewModel.kt | 37 +++++++++++++++++++ .../presentation/base/PresenterBase.kt | 19 ++-------- .../presentation/base/PresenterContract.kt | 6 +++ 3 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 presentation-base/src/main/java/ru/nobird/android/presentation/base/DisposableViewModel.kt create mode 100644 presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterContract.kt diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/DisposableViewModel.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/DisposableViewModel.kt new file mode 100644 index 0000000..b937c1c --- /dev/null +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/DisposableViewModel.kt @@ -0,0 +1,37 @@ +package ru.nobird.android.presentation.base + +import android.os.Bundle +import androidx.annotation.CallSuper +import androidx.lifecycle.ViewModel +import io.reactivex.disposables.CompositeDisposable + +abstract class DisposableViewModel : ViewModel() { + protected val compositeDisposable = CompositeDisposable() + + protected val nestedDisposables: MutableList = arrayListOf() + + @CallSuper + override fun onCleared() { + nestedDisposables.forEach { it.onCleared() } + compositeDisposable.dispose() + } + + @CallSuper + open fun onSaveInstanceState(outState: Bundle) { + nestedDisposables.forEachIndexed { index, nestedPresenter -> + val bundle = Bundle() + nestedPresenter.onSaveInstanceState(bundle) + + outState.putBundle("${nestedPresenter::class.java.canonicalName}:$index", bundle) + } + } + + @CallSuper + open fun onRestoreInstanceState(savedInstanceState: Bundle) { + nestedDisposables.forEachIndexed { index, nestedPresenter -> + savedInstanceState + .getBundle("${nestedPresenter::class.java.canonicalName}:$index") + ?.let(nestedPresenter::onRestoreInstanceState) + } + } +} \ No newline at end of file diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt index 3f92897..ce42a10 100644 --- a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt @@ -1,19 +1,14 @@ package ru.nobird.android.presentation.base -import android.os.Bundle import androidx.annotation.CallSuper -import androidx.lifecycle.ViewModel -import io.reactivex.disposables.CompositeDisposable - -abstract class PresenterBase : ViewModel() { - protected val compositeDisposable = CompositeDisposable() +abstract class PresenterBase : DisposableViewModel(), PresenterContract { @Volatile var view: V? = null private set @CallSuper - open fun attachView(view: V) { + override fun attachView(view: V) { val previousView = this.view check(previousView == null) { "Previous view is not detached! previousView = $previousView" } @@ -22,7 +17,7 @@ abstract class PresenterBase : ViewModel() { } @CallSuper - open fun detachView(view: V) { + override fun detachView(view: V) { val previousView = this.view if (previousView === view) { @@ -31,12 +26,4 @@ abstract class PresenterBase : ViewModel() { throw IllegalStateException("Unexpected view! previousView = $previousView, getView to unbind = $view") } } - - @CallSuper - override fun onCleared() { - compositeDisposable.dispose() - } - - open fun onSaveInstanceState(outState: Bundle) {} - open fun onRestoreInstanceState(savedInstanceState: Bundle) {} } diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterContract.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterContract.kt new file mode 100644 index 0000000..3053f7b --- /dev/null +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterContract.kt @@ -0,0 +1,6 @@ +package ru.nobird.android.presentation.base + +interface PresenterContract { + fun attachView(view: V) + fun detachView(view: V) +} \ No newline at end of file From ec47f43633509f08a73192f4ebc0a8b05fbfea3d Mon Sep 17 00:00:00 2001 From: Ruslan Davletshin Date: Sun, 16 Feb 2020 21:25:31 +0300 Subject: [PATCH 2/6] add presenter actions --- .../base/DefaultPresenterViewContainer.kt | 27 +++++++++++++++++++ .../presentation/base/PresenterBase.kt | 25 +++++++---------- .../base/PresenterViewContainer.kt | 3 +++ .../presentation/base/ViewContainer.kt | 5 ++++ .../base/action/PresenterAction.kt | 9 +++++++ 5 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 presentation-base/src/main/java/ru/nobird/android/presentation/base/DefaultPresenterViewContainer.kt create mode 100644 presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterViewContainer.kt create mode 100644 presentation-base/src/main/java/ru/nobird/android/presentation/base/ViewContainer.kt create mode 100644 presentation-base/src/main/java/ru/nobird/android/presentation/base/action/PresenterAction.kt diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/DefaultPresenterViewContainer.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/DefaultPresenterViewContainer.kt new file mode 100644 index 0000000..1cb9705 --- /dev/null +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/DefaultPresenterViewContainer.kt @@ -0,0 +1,27 @@ +package ru.nobird.android.presentation.base + +import androidx.annotation.CallSuper + +class DefaultPresenterViewContainer : PresenterViewContainer { + @Volatile + override var view: V? = null + private set + + @CallSuper + override fun attachView(view: V) { + val previousView = this.view + + check(previousView == null) { "Previous view is not detached! previousView = $previousView" } + + this.view = view + } + + @CallSuper + override fun detachView(view: V) { + val previousView = this.view + + check(previousView === view) { "Unexpected view! previousView = $previousView, getView to unbind = $view" } + + this.view = null + } +} \ No newline at end of file diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt index ce42a10..f5a848f 100644 --- a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt @@ -1,29 +1,22 @@ package ru.nobird.android.presentation.base import androidx.annotation.CallSuper +import ru.nobird.android.presentation.base.action.PresenterAction -abstract class PresenterBase : DisposableViewModel(), PresenterContract { - @Volatile - var view: V? = null - private set +abstract class PresenterBase( + private val presenterViewContainer: PresenterViewContainer = DefaultPresenterViewContainer() +) : DisposableViewModel(), PresenterViewContainer by presenterViewContainer { + protected val actions: MutableList> = arrayListOf() @CallSuper override fun attachView(view: V) { - val previousView = this.view - - check(previousView == null) { "Previous view is not detached! previousView = $previousView" } - - this.view = view + presenterViewContainer.attachView(view) + actions.forEach { it.attachView(view) } } @CallSuper override fun detachView(view: V) { - val previousView = this.view - - if (previousView === view) { - this.view = null - } else { - throw IllegalStateException("Unexpected view! previousView = $previousView, getView to unbind = $view") - } + actions.forEach { it.detachView(view) } + presenterViewContainer.detachView(view) } } diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterViewContainer.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterViewContainer.kt new file mode 100644 index 0000000..c99ab23 --- /dev/null +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterViewContainer.kt @@ -0,0 +1,3 @@ +package ru.nobird.android.presentation.base + +interface PresenterViewContainer : ViewContainer, PresenterContract \ No newline at end of file diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/ViewContainer.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/ViewContainer.kt new file mode 100644 index 0000000..0149491 --- /dev/null +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/ViewContainer.kt @@ -0,0 +1,5 @@ +package ru.nobird.android.presentation.base + +interface ViewContainer { + val view: V? +} \ No newline at end of file diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/action/PresenterAction.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/action/PresenterAction.kt new file mode 100644 index 0000000..0fe4d52 --- /dev/null +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/action/PresenterAction.kt @@ -0,0 +1,9 @@ +package ru.nobird.android.presentation.base.action + +import ru.nobird.android.presentation.base.DisposableViewModel +import ru.nobird.android.presentation.base.PresenterContract + +abstract class PresenterAction : PresenterContract, DisposableViewModel() { + override fun attachView(view: V) {} + override fun detachView(view: V) {} +} \ No newline at end of file From 44305371eea51b178eb7d965624c91fec452919a Mon Sep 17 00:00:00 2001 From: Ruslan Davletshin Date: Sun, 16 Feb 2020 21:31:37 +0300 Subject: [PATCH 3/6] actions -> delegates --- .../ru/nobird/android/presentation/base/PresenterBase.kt | 8 ++++---- .../PresenterAction.kt => delegate/PresenterDelegate.kt} | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) rename presentation-base/src/main/java/ru/nobird/android/presentation/base/{action/PresenterAction.kt => delegate/PresenterDelegate.kt} (60%) diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt index f5a848f..b70d31f 100644 --- a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt @@ -1,22 +1,22 @@ package ru.nobird.android.presentation.base import androidx.annotation.CallSuper -import ru.nobird.android.presentation.base.action.PresenterAction +import ru.nobird.android.presentation.base.delegate.PresenterDelegate abstract class PresenterBase( private val presenterViewContainer: PresenterViewContainer = DefaultPresenterViewContainer() ) : DisposableViewModel(), PresenterViewContainer by presenterViewContainer { - protected val actions: MutableList> = arrayListOf() + protected val delegates: MutableList> = arrayListOf() @CallSuper override fun attachView(view: V) { presenterViewContainer.attachView(view) - actions.forEach { it.attachView(view) } + delegates.forEach { it.attachView(view) } } @CallSuper override fun detachView(view: V) { - actions.forEach { it.detachView(view) } + delegates.forEach { it.detachView(view) } presenterViewContainer.detachView(view) } } diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/action/PresenterAction.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/delegate/PresenterDelegate.kt similarity index 60% rename from presentation-base/src/main/java/ru/nobird/android/presentation/base/action/PresenterAction.kt rename to presentation-base/src/main/java/ru/nobird/android/presentation/base/delegate/PresenterDelegate.kt index 0fe4d52..bd4039a 100644 --- a/presentation-base/src/main/java/ru/nobird/android/presentation/base/action/PresenterAction.kt +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/delegate/PresenterDelegate.kt @@ -1,9 +1,9 @@ -package ru.nobird.android.presentation.base.action +package ru.nobird.android.presentation.base.delegate import ru.nobird.android.presentation.base.DisposableViewModel import ru.nobird.android.presentation.base.PresenterContract -abstract class PresenterAction : PresenterContract, DisposableViewModel() { +abstract class PresenterDelegate : PresenterContract, DisposableViewModel() { override fun attachView(view: V) {} override fun detachView(view: V) {} } \ No newline at end of file From f50f1f5cd45ecd748c8f5ce2191eb79f1ad1bd81 Mon Sep 17 00:00:00 2001 From: Ruslan Davletshin Date: Sun, 16 Feb 2020 21:46:42 +0300 Subject: [PATCH 4/6] optimisations --- .../nobird/android/presentation/base/DisposableViewModel.kt | 2 +- .../ru/nobird/android/presentation/base/PresenterBase.kt | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/DisposableViewModel.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/DisposableViewModel.kt index b937c1c..5b21832 100644 --- a/presentation-base/src/main/java/ru/nobird/android/presentation/base/DisposableViewModel.kt +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/DisposableViewModel.kt @@ -8,7 +8,7 @@ import io.reactivex.disposables.CompositeDisposable abstract class DisposableViewModel : ViewModel() { protected val compositeDisposable = CompositeDisposable() - protected val nestedDisposables: MutableList = arrayListOf() + protected open val nestedDisposables: List = emptyList() @CallSuper override fun onCleared() { diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt index b70d31f..1835eb6 100644 --- a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt @@ -6,7 +6,10 @@ import ru.nobird.android.presentation.base.delegate.PresenterDelegate abstract class PresenterBase( private val presenterViewContainer: PresenterViewContainer = DefaultPresenterViewContainer() ) : DisposableViewModel(), PresenterViewContainer by presenterViewContainer { - protected val delegates: MutableList> = arrayListOf() + protected open val delegates: List> = emptyList() + + override val nestedDisposables: List + get() = delegates @CallSuper override fun attachView(view: V) { From 8cbeeee537cc0358aedeec6f4c9bf11c8e4aa07e Mon Sep 17 00:00:00 2001 From: Ruslan Davletshin Date: Sun, 16 Feb 2020 21:47:59 +0300 Subject: [PATCH 5/6] presentation:base:1.1.0 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 2291480..68b2add 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -6,7 +6,7 @@ ext.versions = [ viewNavigationName : '1.0.2', viewInjectionName : '1.0.0', - presentationBaseName : '1.0.0', + presentationBaseName : '1.1.0', minSdk : 16, targetSdk : 28, From 82d1368fc7fa81906a86e2339e0f1641c7493e87 Mon Sep 17 00:00:00 2001 From: Ruslan Davletshin Date: Sun, 14 Jun 2020 00:30:30 +0300 Subject: [PATCH 6/6] presentation:base:1.1.1 --- dependencies.gradle | 2 +- .../java/ru/nobird/android/presentation/base/PresenterBase.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 68b2add..0b2d416 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -6,7 +6,7 @@ ext.versions = [ viewNavigationName : '1.0.2', viewInjectionName : '1.0.0', - presentationBaseName : '1.1.0', + presentationBaseName : '1.1.1', minSdk : 16, targetSdk : 28, diff --git a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt index 1835eb6..aee5dbf 100644 --- a/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt +++ b/presentation-base/src/main/java/ru/nobird/android/presentation/base/PresenterBase.kt @@ -6,7 +6,7 @@ import ru.nobird.android.presentation.base.delegate.PresenterDelegate abstract class PresenterBase( private val presenterViewContainer: PresenterViewContainer = DefaultPresenterViewContainer() ) : DisposableViewModel(), PresenterViewContainer by presenterViewContainer { - protected open val delegates: List> = emptyList() + protected open val delegates: List> = emptyList() override val nestedDisposables: List get() = delegates