From 589cb91fffe0dce2df7f7cf4590ed32db577d4c8 Mon Sep 17 00:00:00 2001 From: Paul Woitaschek Date: Mon, 30 Mar 2020 16:37:13 +0200 Subject: [PATCH] Introduce Kotlin (and Java 8) (#585) * Introduce kotlin and converted the ControllerChangeType to kotlin. * Migrated the ThreadUtils to kotlin. * Migrated the TransactionIndexer to kotlin. * Migrated the ChangeHandlerFrameLayout to kotlin. * Migrated Conductor to kotlin. * Added RestrictTo annotations. * Migrated the RouterRequiringFunc to kotlin. * Migrated the RouterTransaction to kotlin * Make use of diamonds. * Make use of lambdas and method references. * Use an interface with default implementations for the LifecycleListener. * Simplify the attachRouter function. * Updated the code style and checkin the idea folder. * Use a Controller extension function for the router transaction. * Use let's instead of forced !! casts. * Added default implementations of ControllerChangeListener * Migrated the NoOpControllerChangeHandler to kotlin. * Use a top level extension function for the asTransaction function. * Add JvmField annotations to the ControllerChangeType fields. * Use the local variables instead of calling the controller again. --- .gitignore | 1 - .idea/.gitignore | 8 + .idea/codeStyles/Project.xml | 129 +++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + build.gradle | 22 ++ conductor-lint/build.gradle | 3 - .../androidx-transition/build.gradle | 5 - .../arch-components-lifecycle/build.gradle | 5 - conductor-modules/autodispose/build.gradle | 5 - conductor-modules/rxlifecycle/build.gradle | 5 - conductor-modules/rxlifecycle2/build.gradle | 5 - conductor-modules/viewpager/build.gradle | 5 - conductor/build.gradle | 7 +- .../com/bluelinelabs/conductor/Backstack.java | 5 +- .../conductor/ChangeHandlerFrameLayout.java | 56 ----- .../conductor/ChangeHandlerFrameLayout.kt | 60 ++++++ .../com/bluelinelabs/conductor/Conductor.java | 44 ---- .../com/bluelinelabs/conductor/Conductor.kt | 31 +++ .../bluelinelabs/conductor/Controller.java | 204 +++++++++++------- .../conductor/ControllerChangeHandler.java | 106 ++++----- .../conductor/ControllerChangeType.java | 26 --- .../conductor/ControllerChangeType.kt | 18 ++ .../conductor/ControllerHostedRouter.java | 15 +- .../com/bluelinelabs/conductor/Router.java | 135 ++++++------ .../conductor/RouterTransaction.java | 140 ------------ .../conductor/RouterTransaction.kt | 123 +++++++++++ .../SharedElementTransitionChangeHandler.java | 130 +++++------ .../TransitionChangeHandler.java | 25 +-- .../conductor/internal/LifecycleHandler.java | 15 +- .../internal/NoOpControllerChangeHandler.java | 27 --- .../internal/NoOpControllerChangeHandler.kt | 22 ++ .../internal/RouterRequiringFunc.java | 5 - .../conductor/internal/RouterRequiringFunc.kt | 9 + .../conductor/internal/ThreadUtils.java | 20 -- .../conductor/internal/ThreadUtils.kt | 17 ++ .../internal/TransactionIndexer.java | 24 --- .../conductor/internal/TransactionIndexer.kt | 25 +++ .../conductor/internal/ViewAttachHandler.java | 9 +- ...rollerLifecycleActivityReferenceTests.java | 14 +- .../conductor/ControllerTests.java | 8 +- .../conductor/ControllerTransactionTests.java | 2 +- .../bluelinelabs/conductor/RouterTests.java | 61 +++--- .../conductor/util/TestController.java | 5 +- .../controllers/ArchLifecycleController.java | 13 +- .../controllers/AutodisposeController.java | 5 +- .../ExternalModulesController.java | 11 +- .../demo/controllers/HomeController.java | 13 +- .../controllers/RxLifecycle2Controller.java | 5 +- .../controllers/RxLifecycleController.java | 5 +- .../base/RefWatchingController.java | 1 + dependencies.gradle | 3 + 51 files changed, 879 insertions(+), 763 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/ChangeHandlerFrameLayout.java create mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/ChangeHandlerFrameLayout.kt delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/Conductor.java create mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/Conductor.kt delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeType.java create mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeType.kt delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/RouterTransaction.java create mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/RouterTransaction.kt delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/internal/NoOpControllerChangeHandler.java create mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/internal/NoOpControllerChangeHandler.kt delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/internal/RouterRequiringFunc.java create mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/internal/RouterRequiringFunc.kt delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/internal/ThreadUtils.java create mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/internal/ThreadUtils.kt delete mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/internal/TransactionIndexer.java create mode 100644 conductor/src/main/java/com/bluelinelabs/conductor/internal/TransactionIndexer.kt diff --git a/.gitignore b/.gitignore index 38c91f6..36c6595 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ .checkstyle # IntelliJ IDEA -.idea *.iml *.ipr *.iws diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b70bf4a --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +/libraries +/runConfigurations.xml +/misc.xml +/vcs.xml +/workspace.xml +/caches +/gradle.xml +/modules.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..a31575d --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,129 @@ + + + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+ + +
+
\ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8726026..0ba9b6f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,14 @@ buildscript { + + apply from: rootProject.file('dependencies.gradle') + repositories { jcenter() google() } dependencies { classpath 'com.android.tools.build:gradle:3.6.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" } } @@ -14,6 +18,24 @@ allprojects { maven { url 'https://maven.google.com' } jcenter() } + + plugins.withType(com.android.build.gradle.BasePlugin).configureEach { plugin -> + plugin.extension.compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + } + + tasks.withType(JavaCompile).configureEach { task -> + task.sourceCompatibility = JavaVersion.VERSION_1_8 + task.targetCompatibility = JavaVersion.VERSION_1_8 + } + + tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile).configureEach { task -> + task.kotlinOptions { + jvmTarget = "1.8" + } + } } apply from: rootProject.file('dependencies.gradle') diff --git a/conductor-lint/build.gradle b/conductor-lint/build.gradle index 4062cd0..ea377c2 100644 --- a/conductor-lint/build.gradle +++ b/conductor-lint/build.gradle @@ -1,8 +1,5 @@ apply plugin: 'java' -targetCompatibility = JavaVersion.VERSION_1_7 -sourceCompatibility = JavaVersion.VERSION_1_7 - configurations { lintChecks } diff --git a/conductor-modules/androidx-transition/build.gradle b/conductor-modules/androidx-transition/build.gradle index 7fd61fd..9a91c6d 100644 --- a/conductor-modules/androidx-transition/build.gradle +++ b/conductor-modules/androidx-transition/build.gradle @@ -9,11 +9,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion rootProject.ext.compileSdkVersion - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion diff --git a/conductor-modules/arch-components-lifecycle/build.gradle b/conductor-modules/arch-components-lifecycle/build.gradle index a370097..01bd1fe 100644 --- a/conductor-modules/arch-components-lifecycle/build.gradle +++ b/conductor-modules/arch-components-lifecycle/build.gradle @@ -6,11 +6,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion rootProject.ext.compileSdkVersion - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion diff --git a/conductor-modules/autodispose/build.gradle b/conductor-modules/autodispose/build.gradle index cbb8e22..d723191 100644 --- a/conductor-modules/autodispose/build.gradle +++ b/conductor-modules/autodispose/build.gradle @@ -6,11 +6,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion rootProject.ext.compileSdkVersion - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion diff --git a/conductor-modules/rxlifecycle/build.gradle b/conductor-modules/rxlifecycle/build.gradle index 4a0e0c2..8bf5539 100644 --- a/conductor-modules/rxlifecycle/build.gradle +++ b/conductor-modules/rxlifecycle/build.gradle @@ -6,11 +6,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion rootProject.ext.compileSdkVersion - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion diff --git a/conductor-modules/rxlifecycle2/build.gradle b/conductor-modules/rxlifecycle2/build.gradle index 3995a64..ee39683 100644 --- a/conductor-modules/rxlifecycle2/build.gradle +++ b/conductor-modules/rxlifecycle2/build.gradle @@ -6,11 +6,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion rootProject.ext.compileSdkVersion - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion diff --git a/conductor-modules/viewpager/build.gradle b/conductor-modules/viewpager/build.gradle index e9477fd..027f9e3 100644 --- a/conductor-modules/viewpager/build.gradle +++ b/conductor-modules/viewpager/build.gradle @@ -3,11 +3,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion rootProject.ext.compileSdkVersion - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion diff --git a/conductor/build.gradle b/conductor/build.gradle index bec9f5a..d0184cf 100644 --- a/conductor/build.gradle +++ b/conductor/build.gradle @@ -1,13 +1,9 @@ apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' android { compileSdkVersion rootProject.ext.compileSdkVersion - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } - defaultConfig { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion @@ -26,6 +22,7 @@ dependencies { testImplementation rootProject.ext.roboelectric api rootProject.ext.androidxAnnotations + api kotlinStd lintChecks project(path: ':conductor-lint', configuration: 'lintChecks') } diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/Backstack.java b/conductor/src/main/java/com/bluelinelabs/conductor/Backstack.java index 39d0e5c..b40d433 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/Backstack.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/Backstack.java @@ -1,6 +1,7 @@ package com.bluelinelabs.conductor; import android.os.Bundle; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -58,7 +59,7 @@ class Backstack implements Iterable { @NonNull RouterTransaction pop() { RouterTransaction popped = backstack.pop(); - popped.controller.destroy(); + popped.controller().destroy(); return popped; } @@ -89,7 +90,7 @@ class Backstack implements Iterable { boolean contains(@NonNull Controller controller) { for (RouterTransaction transaction : backstack) { - if (controller == transaction.controller) { + if (controller == transaction.controller()) { return true; } } diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/ChangeHandlerFrameLayout.java b/conductor/src/main/java/com/bluelinelabs/conductor/ChangeHandlerFrameLayout.java deleted file mode 100644 index 24f4bba..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/ChangeHandlerFrameLayout.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.bluelinelabs.conductor; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener; - -/** - * A FrameLayout implementation that can be used to block user interactions while - * {@link ControllerChangeHandler}s are performing changes. It is not required to use this - * ViewGroup, but it can be helpful. - */ -public class ChangeHandlerFrameLayout extends FrameLayout implements ControllerChangeListener { - - private int inProgressTransactionCount; - - public ChangeHandlerFrameLayout(Context context) { - super(context); - } - - public ChangeHandlerFrameLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ChangeHandlerFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public ChangeHandlerFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return (inProgressTransactionCount > 0) || super.onInterceptTouchEvent(ev); - } - - @Override - public void onChangeStarted(@Nullable Controller to, @Nullable Controller from, boolean isPush, @NonNull ViewGroup container, @NonNull ControllerChangeHandler handler) { - inProgressTransactionCount++; - } - - @Override - public void onChangeCompleted(@Nullable Controller to, @Nullable Controller from, boolean isPush, @NonNull ViewGroup container, @NonNull ControllerChangeHandler handler) { - inProgressTransactionCount--; - } - -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/ChangeHandlerFrameLayout.kt b/conductor/src/main/java/com/bluelinelabs/conductor/ChangeHandlerFrameLayout.kt new file mode 100644 index 0000000..6e779f6 --- /dev/null +++ b/conductor/src/main/java/com/bluelinelabs/conductor/ChangeHandlerFrameLayout.kt @@ -0,0 +1,60 @@ +package com.bluelinelabs.conductor + +import android.annotation.TargetApi +import android.content.Context +import android.os.Build +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.ViewGroup +import android.widget.FrameLayout +import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener + +/** + * A FrameLayout implementation that can be used to block user interactions while + * [ControllerChangeHandler]s are performing changes. It is not required to use this + * ViewGroup, but it can be helpful. + */ +class ChangeHandlerFrameLayout : FrameLayout, ControllerChangeListener { + + private var inProgressTransactionCount = 0 + + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super( + context, + attrs, + defStyleAttr, + defStyleRes + ) + + override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { + return inProgressTransactionCount > 0 || super.onInterceptTouchEvent(ev) + } + + override fun onChangeStarted( + to: Controller?, + from: Controller?, + isPush: Boolean, + container: ViewGroup, + handler: ControllerChangeHandler + ) { + inProgressTransactionCount++ + } + + override fun onChangeCompleted( + to: Controller?, + from: Controller?, + isPush: Boolean, + container: ViewGroup, + handler: ControllerChangeHandler + ) { + inProgressTransactionCount-- + } +} \ No newline at end of file diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/Conductor.java b/conductor/src/main/java/com/bluelinelabs/conductor/Conductor.java deleted file mode 100644 index f1d0d02..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/Conductor.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.bluelinelabs.conductor; - -import android.app.Activity; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; -import android.view.ViewGroup; - -import com.bluelinelabs.conductor.internal.LifecycleHandler; -import com.bluelinelabs.conductor.internal.ThreadUtils; - -/** - * Point of initial interaction with Conductor. Used to attach a {@link Router} to your Activity. - */ -public final class Conductor { - - private Conductor() {} - - /** - * Conductor will create a {@link Router} that has been initialized for your Activity and containing ViewGroup. - * If an existing {@link Router} is already associated with this Activity/ViewGroup pair, either in memory - * or in the savedInstanceState, that router will be used and rebound instead of creating a new one with - * an empty backstack. - * - * @param activity The Activity that will host the {@link Router} being attached. - * @param container The ViewGroup in which the {@link Router}'s {@link Controller} views will be hosted - * @param savedInstanceState The savedInstanceState passed into the hosting Activity's onCreate method. Used - * for restoring the Router's state if possible. - * @return A fully configured {@link Router} instance for use with this Activity/ViewGroup pair. - */ - @NonNull @UiThread - public static Router attachRouter(@NonNull Activity activity, @NonNull ViewGroup container, @Nullable Bundle savedInstanceState) { - ThreadUtils.ensureMainThread(); - - LifecycleHandler lifecycleHandler = LifecycleHandler.install(activity); - - Router router = lifecycleHandler.getRouter(container, savedInstanceState); - router.rebindIfNeeded(); - - return router; - } - -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/Conductor.kt b/conductor/src/main/java/com/bluelinelabs/conductor/Conductor.kt new file mode 100644 index 0000000..b9d3712 --- /dev/null +++ b/conductor/src/main/java/com/bluelinelabs/conductor/Conductor.kt @@ -0,0 +1,31 @@ +@file:JvmName("Conductor") + +package com.bluelinelabs.conductor + +import android.app.Activity +import android.os.Bundle +import android.view.ViewGroup +import androidx.annotation.UiThread +import com.bluelinelabs.conductor.internal.LifecycleHandler +import com.bluelinelabs.conductor.internal.ensureMainThread + + +/** + * Conductor will create a [Router] that has been initialized for your Activity and containing ViewGroup. + * If an existing [Router] is already associated with this Activity/ViewGroup pair, either in memory + * or in the savedInstanceState, that router will be used and rebound instead of creating a new one with + * an empty backstack. + * + * @receiver The Activity that will host the [Router] being attached. + * @param container The ViewGroup in which the [Router]'s [Controller] views will be hosted + * @param savedInstanceState The savedInstanceState passed into the hosting Activity's onCreate method. Used + * for restoring the Router's state if possible. + * @return A fully configured [Router] instance for use with this Activity/ViewGroup pair. + */ +@UiThread +fun Activity.attachRouter(container: ViewGroup, savedInstanceState: Bundle?): Router { + ensureMainThread() + return LifecycleHandler.install(this) + .getRouter(container, savedInstanceState) + .also { it.rebindIfNeeded() } +} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/Controller.java b/conductor/src/main/java/com/bluelinelabs/conductor/Controller.java index 7d70022..f9c2ca0 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/Controller.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/Controller.java @@ -18,6 +18,10 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.bluelinelabs.conductor.internal.ClassUtils; import com.bluelinelabs.conductor.internal.RouterRequiringFunc; import com.bluelinelabs.conductor.internal.ViewAttachHandler; @@ -28,14 +32,9 @@ import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.List; import java.util.UUID; -import androidx.annotation.IdRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - /** * A Controller manages portions of the UI. It is similar to an Activity or Fragment in that it manages its * own lifecycle and controls interactions between the UI and whatever logic is required. It is, however, @@ -108,10 +107,10 @@ public abstract class Controller { Controller controller; try { if (bundleConstructor != null) { - controller = (Controller)bundleConstructor.newInstance(args); + controller = (Controller) bundleConstructor.newInstance(args); } else { //noinspection ConstantConditions - controller = (Controller)getDefaultConstructor(constructors).newInstance(); + controller = (Controller) getDefaultConstructor(constructors).newInstance(); // Restore the args that existed before the last process death if (args != null) { @@ -190,7 +189,7 @@ public abstract class Controller { * the same container unless you have a great reason to do so (ex: ViewPagers). * * @param container The ViewGroup that hosts the child Router - * @param tag The router's tag or {@code null} if none is needed + * @param tag The router's tag or {@code null} if none is needed */ @NonNull public final Router getChildRouter(@NonNull ViewGroup container, @Nullable String tag) { @@ -205,8 +204,8 @@ public abstract class Controller { * The only time this method will return {@code null} is when the child router does not exist prior * to calling this method and the createIfNeeded parameter is set to false. * - * @param container The ViewGroup that hosts the child Router - * @param tag The router's tag or {@code null} if none is needed + * @param container The ViewGroup that hosts the child Router + * @param tag The router's tag or {@code null} if none is needed * @param createIfNeeded If true, a router will be created if one does not yet exist. Else {@code null} will be returned in this case. */ @Nullable @@ -394,7 +393,8 @@ public abstract class Controller { * * @param view The View to which this Controller should be bound. */ - protected void onDestroyView(@NonNull View view) { } + protected void onDestroyView(@NonNull View view) { + } /** * Called when this Controller begins the process of being swapped in or out of the host view. @@ -402,7 +402,8 @@ public abstract class Controller { * @param changeHandler The {@link ControllerChangeHandler} that's managing the swap * @param changeType The type of change that's occurring */ - protected void onChangeStarted(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { } + protected void onChangeStarted(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { + } /** * Called when this Controller completes the process of being swapped in or out of the host view. @@ -410,59 +411,69 @@ public abstract class Controller { * @param changeHandler The {@link ControllerChangeHandler} that's managing the swap * @param changeType The type of change that occurred */ - protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { } + protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { + } /** * Called when this Controller has a Context available to it. This will happen very early on in the lifecycle * (before a view is created). If the host activity is re-created (ex: for orientation change), this will be * called again when the new context is available. */ - protected void onContextAvailable(@NonNull Context context) { } + protected void onContextAvailable(@NonNull Context context) { + } /** * Called when this Controller's Context is no longer available. This can happen when the Controller is * destroyed or when the host Activity is destroyed. */ - protected void onContextUnavailable() { } + protected void onContextUnavailable() { + } /** * Called when this Controller is attached to its host ViewGroup * * @param view The View for this Controller (passed for convenience) */ - protected void onAttach(@NonNull View view) { } + protected void onAttach(@NonNull View view) { + } /** * Called when this Controller is detached from its host ViewGroup * * @param view The View for this Controller (passed for convenience) */ - protected void onDetach(@NonNull View view) { } + protected void onDetach(@NonNull View view) { + } /** * Called when this Controller has been destroyed. */ - protected void onDestroy() { } + protected void onDestroy() { + } /** * Called when this Controller's host Activity is started */ - protected void onActivityStarted(@NonNull Activity activity) { } + protected void onActivityStarted(@NonNull Activity activity) { + } /** * Called when this Controller's host Activity is resumed */ - protected void onActivityResumed(@NonNull Activity activity) { } + protected void onActivityResumed(@NonNull Activity activity) { + } /** * Called when this Controller's host Activity is paused */ - protected void onActivityPaused(@NonNull Activity activity) { } + protected void onActivityPaused(@NonNull Activity activity) { + } /** * Called when this Controller's host Activity is stopped */ - protected void onActivityStopped(@NonNull Activity activity) { } + protected void onActivityStopped(@NonNull Activity activity) { + } /** * Called to save this Controller's View state. As Views can be detached and destroyed as part of the @@ -472,7 +483,8 @@ public abstract class Controller { * @param view This Controller's View, passed for convenience * @param outState The Bundle into which the View state should be saved */ - protected void onSaveViewState(@NonNull View view, @NonNull Bundle outState) { } + protected void onSaveViewState(@NonNull View view, @NonNull Bundle outState) { + } /** * Restores data that was saved in the {@link #onSaveViewState(View, Bundle)} method. This should be overridden @@ -481,14 +493,16 @@ public abstract class Controller { * @param view This Controller's View, passed for convenience * @param savedViewState The bundle that has data to be restored */ - protected void onRestoreViewState(@NonNull View view, @NonNull Bundle savedViewState) { } + protected void onRestoreViewState(@NonNull View view, @NonNull Bundle savedViewState) { + } /** * Called to save this Controller's state in the event that its host Activity is destroyed. * * @param outState The Bundle into which data should be saved */ - protected void onSaveInstanceState(@NonNull Bundle outState) { } + protected void onSaveInstanceState(@NonNull Bundle outState) { + } /** * Restores data that was saved in the {@link #onSaveInstanceState(Bundle)} method. This should be overridden @@ -496,33 +510,28 @@ public abstract class Controller { * * @param savedInstanceState The bundle that has data to be restored */ - protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { } + protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { + } /** * Calls startActivity(Intent) from this Controller's host Activity. */ public final void startActivity(@NonNull final Intent intent) { - executeWithRouter(new RouterRequiringFunc() { - @Override public void execute() { router.startActivity(intent); } - }); + executeWithRouter(() -> router.startActivity(intent)); } /** * Calls startActivityForResult(Intent, int) from this Controller's host Activity. */ public final void startActivityForResult(@NonNull final Intent intent, final int requestCode) { - executeWithRouter(new RouterRequiringFunc() { - @Override public void execute() { router.startActivityForResult(instanceId, intent, requestCode); } - }); + executeWithRouter(() -> router.startActivityForResult(instanceId, intent, requestCode)); } /** * Calls startActivityForResult(Intent, int, Bundle) from this Controller's host Activity. */ public final void startActivityForResult(@NonNull final Intent intent, final int requestCode, @Nullable final Bundle options) { - executeWithRouter(new RouterRequiringFunc() { - @Override public void execute() { router.startActivityForResult(instanceId, intent, requestCode, options); } - }); + executeWithRouter(() -> router.startActivityForResult(instanceId, intent, requestCode, options)); } /** @@ -540,9 +549,7 @@ public abstract class Controller { * @param requestCode The request code being registered for. */ public final void registerForActivityResult(final int requestCode) { - executeWithRouter(new RouterRequiringFunc() { - @Override public void execute() { router.registerForActivityResult(instanceId, requestCode); } - }); + executeWithRouter(() -> router.registerForActivityResult(instanceId, requestCode)); } /** @@ -553,7 +560,8 @@ public abstract class Controller { * @param resultCode The resultCode that was returned to the host Activity's onActivityResult method * @param data The data Intent that was returned to the host Activity's onActivityResult method */ - public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { } + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + } /** * Calls requestPermission(String[], int) from this Controller's host Activity. Results for this request, @@ -564,9 +572,7 @@ public abstract class Controller { public final void requestPermissions(@NonNull final String[] permissions, final int requestCode) { requestedPermissions.addAll(Arrays.asList(permissions)); - executeWithRouter(new RouterRequiringFunc() { - @Override public void execute() { router.requestPermissions(instanceId, permissions, requestCode); } - }); + executeWithRouter(() -> router.requestPermissions(instanceId, permissions, requestCode)); } /** @@ -586,7 +592,8 @@ public abstract class Controller { * @param permissions The array of permissions requested * @param grantResults The results for each permission requested */ - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { } + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + } /** * Should be overridden if this Controller needs to handle the back button being pressed. @@ -600,15 +607,10 @@ public abstract class Controller { childTransactions.addAll(childRouter.getBackstack()); } - Collections.sort(childTransactions, new Comparator() { - @Override - public int compare(RouterTransaction o1, RouterTransaction o2) { - return o2.transactionIndex - o1.transactionIndex; - } - }); + Collections.sort(childTransactions, (o1, o2) -> o2.getTransactionIndex() - o1.getTransactionIndex()); for (RouterTransaction transaction : childTransactions) { - Controller childController = transaction.controller; + Controller childController = transaction.controller(); if (childController.isAttached() && childController.getRouter().handleBack()) { return true; @@ -728,10 +730,11 @@ public abstract class Controller { * Adds option items to the host Activity's standard options menu. This will only be called if * {@link #setHasOptionsMenu(boolean)} has been called. * - * @param menu The menu into which your options should be placed. + * @param menu The menu into which your options should be placed. * @param inflater The inflater that can be used to inflate your menu items. */ - public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { } + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + } /** * Prepare the screen's options menu to be displayed. This is called directly before showing the @@ -739,7 +742,8 @@ public abstract class Controller { * * @param menu The menu that will be displayed */ - public void onPrepareOptionsMenu(@NonNull Menu menu) { } + public void onPrepareOptionsMenu(@NonNull Menu menu) { + } /** * Called when an option menu item has been selected by the user. @@ -918,8 +922,8 @@ public abstract class Controller { for (ControllerHostedRouter childRouter : childRouters) { for (RouterTransaction childTransaction : childRouter.backstack) { - if (childTransaction.controller.awaitingParentAttach) { - childTransaction.controller.attach(childTransaction.controller.view); + if (childTransaction.controller().awaitingParentAttach) { + childTransaction.controller().attach(childTransaction.controller().view); } } @@ -1063,7 +1067,7 @@ public abstract class Controller { View containerView = view.findViewById(childRouter.getHostId()); if (containerView != null && containerView instanceof ViewGroup) { - childRouter.setHost(this, (ViewGroup)containerView); + childRouter.setHost(this, (ViewGroup) containerView); childRouter.rebindIfNeeded(); } } @@ -1353,46 +1357,84 @@ public abstract class Controller { return null; } - /** Modes that will influence when the Controller will allow its view to be destroyed */ + /** + * Modes that will influence when the Controller will allow its view to be destroyed + */ public enum RetainViewMode { - /** The Controller will release its reference to its view as soon as it is detached. */ + /** + * The Controller will release its reference to its view as soon as it is detached. + */ RELEASE_DETACH, - /** The Controller will retain its reference to its view when detached, but will still release the reference when a config change occurs. */ + /** + * The Controller will retain its reference to its view when detached, but will still release the reference when a config change occurs. + */ RETAIN_DETACH } - /** Allows external classes to listen for lifecycle events in a Controller */ - public static abstract class LifecycleListener { + /** + * Allows external classes to listen for lifecycle events in a Controller + */ + public interface LifecycleListener { - public void onChangeStart(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { } - public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { } + default void onChangeStart(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { + } - public void preCreateView(@NonNull Controller controller) { } - public void postCreateView(@NonNull Controller controller, @NonNull View view) { } + default void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { + } - public void preAttach(@NonNull Controller controller, @NonNull View view) { } - public void postAttach(@NonNull Controller controller, @NonNull View view) { } + default void preCreateView(@NonNull Controller controller) { + } - public void preDetach(@NonNull Controller controller, @NonNull View view) { } - public void postDetach(@NonNull Controller controller, @NonNull View view) { } + default void postCreateView(@NonNull Controller controller, @NonNull View view) { + } - public void preDestroyView(@NonNull Controller controller, @NonNull View view) { } - public void postDestroyView(@NonNull Controller controller) { } + default void preAttach(@NonNull Controller controller, @NonNull View view) { + } - public void preDestroy(@NonNull Controller controller) { } - public void postDestroy(@NonNull Controller controller) { } + default void postAttach(@NonNull Controller controller, @NonNull View view) { + } - public void preContextAvailable(@NonNull Controller controller) { } - public void postContextAvailable(@NonNull Controller controller, @NonNull Context context) { } + default void preDetach(@NonNull Controller controller, @NonNull View view) { + } - public void preContextUnavailable(@NonNull Controller controller, @NonNull Context context) { } - public void postContextUnavailable(@NonNull Controller controller) { } + default void postDetach(@NonNull Controller controller, @NonNull View view) { + } - public void onSaveInstanceState(@NonNull Controller controller, @NonNull Bundle outState) { } - public void onRestoreInstanceState(@NonNull Controller controller, @NonNull Bundle savedInstanceState) { } + default void preDestroyView(@NonNull Controller controller, @NonNull View view) { + } - public void onSaveViewState(@NonNull Controller controller, @NonNull Bundle outState) { } - public void onRestoreViewState(@NonNull Controller controller, @NonNull Bundle savedViewState) { } + default void postDestroyView(@NonNull Controller controller) { + } + + default void preDestroy(@NonNull Controller controller) { + } + + default void postDestroy(@NonNull Controller controller) { + } + + default void preContextAvailable(@NonNull Controller controller) { + } + + default void postContextAvailable(@NonNull Controller controller, @NonNull Context context) { + } + + default void preContextUnavailable(@NonNull Controller controller, @NonNull Context context) { + } + + default void postContextUnavailable(@NonNull Controller controller) { + } + + default void onSaveInstanceState(@NonNull Controller controller, @NonNull Bundle outState) { + } + + default void onRestoreInstanceState(@NonNull Controller controller, @NonNull Bundle savedInstanceState) { + } + + default void onSaveViewState(@NonNull Controller controller, @NonNull Bundle outState) { + } + + default void onRestoreViewState(@NonNull Controller controller, @NonNull Bundle savedViewState) { + } } diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeHandler.java b/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeHandler.java index f8163fe..44a8605 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeHandler.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeHandler.java @@ -1,12 +1,13 @@ package com.bluelinelabs.conductor; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler; import com.bluelinelabs.conductor.internal.ClassUtils; @@ -49,14 +50,16 @@ public abstract class ControllerChangeHandler { * * @param bundle The Bundle into which data should be stored. */ - public void saveToBundle(@NonNull Bundle bundle) { } + public void saveToBundle(@NonNull Bundle bundle) { + } /** * Restores data that was saved in the {@link #saveToBundle(Bundle bundle)} method. * * @param bundle The bundle that has data to be restored */ - public void restoreFromBundle(@NonNull Bundle bundle) { } + public void restoreFromBundle(@NonNull Bundle bundle) { + } /** * Will be called on change handlers that push a controller if the controller being pushed is @@ -66,13 +69,15 @@ public abstract class ControllerChangeHandler { * @param newTop The Controller that will now be at the top of the backstack or {@code null} * if there will be no new Controller at the top */ - public void onAbortPush(@NonNull ControllerChangeHandler newHandler, @Nullable Controller newTop) { } + public void onAbortPush(@NonNull ControllerChangeHandler newHandler, @Nullable Controller newTop) { + } /** * Will be called on change handlers that push a controller if the controller being pushed is * needs to be attached immediately, without any animations or transitions. */ - public void completeImmediately() { } + public void completeImmediately() { + } /** * Returns a copy of this ControllerChangeHandler. This method is internally used by the library, so @@ -201,38 +206,36 @@ public abstract class ControllerChangeHandler { fromView = null; } - handler.performChange(container, fromView, toView, isPush, new ControllerChangeCompletedListener() { - @Override - public void onChangeCompleted() { - if (from != null) { - from.changeEnded(handler, fromChangeType); - } + handler.performChange(container, fromView, toView, isPush, () -> { + if (from != null) { + from.changeEnded(handler, fromChangeType); + } - if (to != null) { - inProgressChangeHandlers.remove(to.getInstanceId()); - to.changeEnded(handler, toChangeType); - } + if (to != null) { + inProgressChangeHandlers.remove(to.getInstanceId()); + to.changeEnded(handler, toChangeType); + } - for (ControllerChangeListener listener : listeners) { - listener.onChangeCompleted(to, from, isPush, container, handler); - } + for (ControllerChangeListener listener : listeners) { + listener.onChangeCompleted(to, from, isPush, container, handler); + } - if (handler.forceRemoveViewOnPush && fromView != null) { - ViewParent fromParent = fromView.getParent(); - if (fromParent != null && fromParent instanceof ViewGroup) { - ((ViewGroup)fromParent).removeView(fromView); - } + if (handler.forceRemoveViewOnPush && fromView != null) { + ViewParent fromParent = fromView.getParent(); + if (fromParent != null && fromParent instanceof ViewGroup) { + ((ViewGroup) fromParent).removeView(fromView); } + } - if (handler.removesFromViewOnPush() && from != null) { - from.setNeedsAttach(false); - } + if (handler.removesFromViewOnPush() && from != null) { + from.setNeedsAttach(false); } }); } } - protected void onEnd(){ } + protected void onEnd() { + } public boolean removesFromViewOnPush() { return true; @@ -242,24 +245,6 @@ public abstract class ControllerChangeHandler { forceRemoveViewOnPush = force; } - static class ChangeTransaction { - @Nullable final Controller to; - @Nullable final Controller from; - final boolean isPush; - @Nullable final ViewGroup container; - @Nullable final ControllerChangeHandler changeHandler; - @NonNull final List listeners; - - public ChangeTransaction(@Nullable Controller to, @Nullable Controller from, boolean isPush, @Nullable ViewGroup container, @Nullable ControllerChangeHandler changeHandler, @NonNull List listeners) { - this.to = to; - this.from = from; - this.isPush = isPush; - this.container = container; - this.changeHandler = changeHandler; - this.listeners = listeners; - } - } - /** * A listener interface useful for allowing external classes to be notified of change events. */ @@ -273,7 +258,8 @@ public abstract class ControllerChangeHandler { * @param container The containing ViewGroup * @param handler The change handler being used. */ - void onChangeStarted(@Nullable Controller to, @Nullable Controller from, boolean isPush, @NonNull ViewGroup container, @NonNull ControllerChangeHandler handler); + default void onChangeStarted(@Nullable Controller to, @Nullable Controller from, boolean isPush, @NonNull ViewGroup container, @NonNull ControllerChangeHandler handler) { + } /** * Called when a {@link ControllerChangeHandler} has completed changing {@link Controller}s @@ -284,7 +270,31 @@ public abstract class ControllerChangeHandler { * @param container The containing ViewGroup * @param handler The change handler that was used. */ - void onChangeCompleted(@Nullable Controller to, @Nullable Controller from, boolean isPush, @NonNull ViewGroup container, @NonNull ControllerChangeHandler handler); + default void onChangeCompleted(@Nullable Controller to, @Nullable Controller from, boolean isPush, @NonNull ViewGroup container, @NonNull ControllerChangeHandler handler) { + } + } + + static class ChangeTransaction { + @Nullable + final Controller to; + @Nullable + final Controller from; + final boolean isPush; + @Nullable + final ViewGroup container; + @Nullable + final ControllerChangeHandler changeHandler; + @NonNull + final List listeners; + + public ChangeTransaction(@Nullable Controller to, @Nullable Controller from, boolean isPush, @Nullable ViewGroup container, @Nullable ControllerChangeHandler changeHandler, @NonNull List listeners) { + this.to = to; + this.from = from; + this.isPush = isPush; + this.container = container; + this.changeHandler = changeHandler; + this.listeners = listeners; + } } /** diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeType.java b/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeType.java deleted file mode 100644 index 2a6709e..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeType.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.bluelinelabs.conductor; - -/** - * All possible types of {@link Controller} changes to be used in {@link ControllerChangeHandler}s - */ -public enum ControllerChangeType { - /** The Controller is being pushed to the host container */ - PUSH_ENTER(true, true), - - /** The Controller is being pushed to the backstack as another Controller is pushed to the host container */ - PUSH_EXIT(true, false), - - /** The Controller is being popped from the backstack and placed in the host container as another Controller is popped */ - POP_ENTER(false, true), - - /** The Controller is being popped from the host container */ - POP_EXIT(false, false); - - public boolean isPush; - public boolean isEnter; - - ControllerChangeType(boolean isPush, boolean isEnter) { - this.isPush = isPush; - this.isEnter = isEnter; - } -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeType.kt b/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeType.kt new file mode 100644 index 0000000..f70210e --- /dev/null +++ b/conductor/src/main/java/com/bluelinelabs/conductor/ControllerChangeType.kt @@ -0,0 +1,18 @@ +package com.bluelinelabs.conductor + +/** + * All possible types of [Controller] changes to be used in [ControllerChangeHandler]s + */ +enum class ControllerChangeType(@JvmField val isPush: Boolean, @JvmField val isEnter: Boolean) { + /** The Controller is being pushed to the host container */ + PUSH_ENTER(true, true), + + /** The Controller is being pushed to the backstack as another Controller is pushed to the host container */ + PUSH_EXIT(true, false), + + /** The Controller is being popped from the backstack and placed in the host container as another Controller is popped */ + POP_ENTER(false, true), + + /** The Controller is being popped from the host container */ + POP_EXIT(false, false); +} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/ControllerHostedRouter.java b/conductor/src/main/java/com/bluelinelabs/conductor/ControllerHostedRouter.java index 9ef7d1a..707c840 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/ControllerHostedRouter.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/ControllerHostedRouter.java @@ -5,10 +5,11 @@ import android.content.Intent; import android.content.IntentSender; import android.content.IntentSender.SendIntentException; import android.os.Bundle; +import android.view.ViewGroup; + import androidx.annotation.IdRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import android.view.ViewGroup; import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener; import com.bluelinelabs.conductor.internal.TransactionIndexer; @@ -47,7 +48,7 @@ class ControllerHostedRouter extends Router { this.container = container; for (RouterTransaction transaction : backstack) { - transaction.controller.setParentController(controller); + transaction.controller().setParentController(controller); } watchContainerAttach(); @@ -66,8 +67,8 @@ class ControllerHostedRouter extends Router { } } for (RouterTransaction transaction : backstack) { - if (transaction.controller.getView() != null) { - transaction.controller.detach(transaction.controller.getView(), true, false); + if (transaction.controller().getView() != null) { + transaction.controller().detach(transaction.controller().getView(), true, false); } } @@ -79,7 +80,7 @@ class ControllerHostedRouter extends Router { final void setDetachFrozen(boolean frozen) { isDetachFrozen = frozen; for (RouterTransaction transaction : backstack) { - transaction.controller.setDetachFrozen(frozen); + transaction.controller().setDetachFrozen(frozen); } } @@ -92,7 +93,7 @@ class ControllerHostedRouter extends Router { @Override protected void pushToBackstack(@NonNull RouterTransaction entry) { if (isDetachFrozen) { - entry.controller.setDetachFrozen(true); + entry.controller().setDetachFrozen(true); } super.pushToBackstack(entry); } @@ -101,7 +102,7 @@ class ControllerHostedRouter extends Router { public void setBackstack(@NonNull List newBackstack, @Nullable ControllerChangeHandler changeHandler) { if (isDetachFrozen) { for (RouterTransaction transaction : newBackstack) { - transaction.controller.setDetachFrozen(true); + transaction.controller().setDetachFrozen(true); } } super.setBackstack(newBackstack, changeHandler); diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/Router.java b/conductor/src/main/java/com/bluelinelabs/conductor/Router.java index 69f75d9..024b3d7 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/Router.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/Router.java @@ -10,7 +10,10 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import com.bluelinelabs.conductor.Controller.LifecycleListener; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.UiThread; + import com.bluelinelabs.conductor.ControllerChangeHandler.ChangeTransaction; import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeListener; import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler; @@ -23,10 +26,6 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; - /** * A Router implements navigation and backstack handling for {@link Controller}s. Router objects are attached * to Activity/containing ViewGroup pairs. Routers do not directly render or push Views to the container ViewGroup, @@ -93,7 +92,7 @@ public abstract class Router { if (!backstack.isEmpty()) { //noinspection ConstantConditions - if (backstack.peek().controller.handleBack()) { + if (backstack.peek().controller().handleBack()) { return true; } else if (popCurrentController()) { return true; @@ -117,7 +116,7 @@ public abstract class Router { if (transaction == null) { throw new IllegalStateException("Trying to pop the current controller when there are none on the backstack."); } - return popController(transaction.controller); + return popController(transaction.controller()); } /** @@ -131,7 +130,7 @@ public abstract class Router { ThreadUtils.ensureMainThread(); RouterTransaction topTransaction = backstack.peek(); - boolean poppingTopController = topTransaction != null && topTransaction.controller == controller; + boolean poppingTopController = topTransaction != null && topTransaction.controller() == controller; if (poppingTopController) { trackDestroyingController(backstack.pop()); @@ -145,12 +144,12 @@ public abstract class Router { while (iterator.hasNext()) { RouterTransaction transaction = iterator.next(); - if (transaction.controller == controller) { + if (transaction.controller() == controller) { trackDestroyingController(transaction); iterator.remove(); removedTransaction = transaction; } else if (removedTransaction != null) { - if (needsNextTransactionAttach && !transaction.controller.isAttached()) { + if (needsNextTransactionAttach && !transaction.controller().isAttached()) { nextTransaction = transaction; } break; @@ -227,7 +226,7 @@ public abstract class Router { if (popViews && poppedControllers.size() > 0) { RouterTransaction topTransaction = poppedControllers.get(0); - topTransaction.controller().addLifecycleListener(new LifecycleListener() { + topTransaction.controller().addLifecycleListener(new Controller.LifecycleListener() { @Override public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) { if (changeType == ControllerChangeType.POP_EXIT) { @@ -347,7 +346,7 @@ public abstract class Router { @Nullable public Controller getControllerWithInstanceId(@NonNull String instanceId) { for (RouterTransaction transaction : backstack) { - Controller controllerWithId = transaction.controller.findController(instanceId); + Controller controllerWithId = transaction.controller().findController(instanceId); if (controllerWithId != null) { return controllerWithId; } @@ -365,7 +364,7 @@ public abstract class Router { public Controller getControllerWithTag(@NonNull String tag) { for (RouterTransaction transaction : backstack) { if (tag.equals(transaction.tag())) { - return transaction.controller; + return transaction.controller(); } } return null; @@ -417,7 +416,7 @@ public abstract class Router { for (RouterTransaction oldTransaction : oldTransactions) { boolean contains = false; for (RouterTransaction newTransaction : newBackstack) { - if (oldTransaction.controller == newTransaction.controller) { + if (oldTransaction.controller() == newTransaction.controller()) { contains = true; break; } @@ -425,7 +424,7 @@ public abstract class Router { if (!contains) { // Inform the controller that it will be destroyed soon - oldTransaction.controller.isBeingDestroyed = true; + oldTransaction.controller().isBeingDestroyed = true; transactionsToBeRemoved.add(oldTransaction); } } @@ -435,7 +434,7 @@ public abstract class Router { while (backstackIterator.hasNext()) { RouterTransaction transaction = backstackIterator.next(); transaction.onAttachedToRouter(); - setControllerRouter(transaction.controller); + setControllerRouter(transaction.controller()); } if (newBackstack.size() > 0) { @@ -450,10 +449,10 @@ public abstract class Router { RouterTransaction newRootTransaction = newVisibleTransactions.get(0); // Replace the old root with the new one - if (oldRootTransaction == null || oldRootTransaction.controller != newRootTransaction.controller) { + if (oldRootTransaction == null || oldRootTransaction.controller() != newRootTransaction.controller()) { // Ensure the existing root controller is fully pushed to the view hierarchy if (oldRootTransaction != null) { - ControllerChangeHandler.completeHandlerImmediately(oldRootTransaction.controller.getInstanceId()); + ControllerChangeHandler.completeHandlerImmediately(oldRootTransaction.controller().getInstanceId()); } performControllerChange(newRootTransaction, oldRootTransaction, newRootRequiresPush, changeHandler); } @@ -464,7 +463,7 @@ public abstract class Router { if (!newVisibleTransactions.contains(transaction)) { ControllerChangeHandler localHandler = changeHandler != null ? changeHandler.copy() : new SimpleSwapChangeHandler(); localHandler.setForceRemoveViewOnPush(true); - ControllerChangeHandler.completeHandlerImmediately(transaction.controller.getInstanceId()); + ControllerChangeHandler.completeHandlerImmediately(transaction.controller().getInstanceId()); performControllerChange(null, transaction, newRootRequiresPush, localHandler); } } @@ -483,7 +482,7 @@ public abstract class Router { for (int i = oldVisibleTransactions.size() - 1; i >= 0; i--) { RouterTransaction transaction = oldVisibleTransactions.get(i); ControllerChangeHandler localHandler = changeHandler != null ? changeHandler.copy() : new SimpleSwapChangeHandler(); - ControllerChangeHandler.completeHandlerImmediately(transaction.controller.getInstanceId()); + ControllerChangeHandler.completeHandlerImmediately(transaction.controller().getInstanceId()); performControllerChange(null, transaction, false, localHandler); } } @@ -496,13 +495,13 @@ public abstract class Router { // Still need to ensure the controller isn't queued up to be removed later on. boolean willBeRemoved = false; for (ChangeTransaction pendingTransaction : pendingControllerChanges) { - if (pendingTransaction.from == removedTransaction.controller) { + if (pendingTransaction.from == removedTransaction.controller()) { willBeRemoved = true; } } if (!willBeRemoved) { - removedTransaction.controller.destroy(); + removedTransaction.controller().destroy(); } } } @@ -547,10 +546,10 @@ public abstract class Router { while (backstackIterator.hasNext()) { RouterTransaction transaction = backstackIterator.next(); - if (transaction.controller.getNeedsAttach()) { + if (transaction.controller().getNeedsAttach()) { performControllerChange(transaction, null, true, new SimpleSwapChangeHandler(false)); } else { - setControllerRouter(transaction.controller); + setControllerRouter(transaction.controller()); } } } @@ -566,9 +565,9 @@ public abstract class Router { isActivityStopped = false; for (RouterTransaction transaction : backstack) { - transaction.controller.activityStarted(activity); + transaction.controller().activityStarted(activity); - for (Router childRouter : transaction.controller.getChildRouters()) { + for (Router childRouter : transaction.controller().getChildRouters()) { childRouter.onActivityStarted(activity); } } @@ -576,9 +575,9 @@ public abstract class Router { public final void onActivityResumed(@NonNull Activity activity) { for (RouterTransaction transaction : backstack) { - transaction.controller.activityResumed(activity); + transaction.controller().activityResumed(activity); - for (Router childRouter : transaction.controller.getChildRouters()) { + for (Router childRouter : transaction.controller().getChildRouters()) { childRouter.onActivityResumed(activity); } } @@ -586,9 +585,9 @@ public abstract class Router { public final void onActivityPaused(@NonNull Activity activity) { for (RouterTransaction transaction : backstack) { - transaction.controller.activityPaused(activity); + transaction.controller().activityPaused(activity); - for (Router childRouter : transaction.controller.getChildRouters()) { + for (Router childRouter : transaction.controller().getChildRouters()) { childRouter.onActivityPaused(activity); } } @@ -596,9 +595,9 @@ public abstract class Router { public final void onActivityStopped(@NonNull Activity activity) { for (RouterTransaction transaction : backstack) { - transaction.controller.activityStopped(activity); + transaction.controller().activityStopped(activity); - for (Router childRouter : transaction.controller.getChildRouters()) { + for (Router childRouter : transaction.controller().getChildRouters()) { childRouter.onActivityStopped(activity); } } @@ -611,9 +610,9 @@ public abstract class Router { changeListeners.clear(); for (RouterTransaction transaction : backstack) { - transaction.controller.activityDestroyed(activity); + transaction.controller().activityDestroyed(activity); - for (Router childRouter : transaction.controller.getChildRouters()) { + for (Router childRouter : transaction.controller().getChildRouters()) { childRouter.onActivityDestroyed(activity); } } @@ -634,11 +633,11 @@ public abstract class Router { pendingControllerChanges.clear(); // rely on backstack based restoration in rebindIfNeeded for (RouterTransaction transaction : backstack) { - if (ControllerChangeHandler.completeHandlerImmediately(transaction.controller.getInstanceId())) { - transaction.controller.setNeedsAttach(true); + if (ControllerChangeHandler.completeHandlerImmediately(transaction.controller().getInstanceId())) { + transaction.controller().setNeedsAttach(true); } - transaction.controller.prepareForHostDetach(); + transaction.controller().prepareForHostDetach(); } } @@ -658,15 +657,15 @@ public abstract class Router { Iterator backstackIterator = backstack.reverseIterator(); while (backstackIterator.hasNext()) { - setControllerRouter(backstackIterator.next().controller); + setControllerRouter(backstackIterator.next().controller()); } } public final void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { for (RouterTransaction transaction : backstack) { - transaction.controller.createOptionsMenu(menu, inflater); + transaction.controller().createOptionsMenu(menu, inflater); - for (Router childRouter : transaction.controller.getChildRouters()) { + for (Router childRouter : transaction.controller().getChildRouters()) { childRouter.onCreateOptionsMenu(menu, inflater); } } @@ -674,9 +673,9 @@ public abstract class Router { public final void onPrepareOptionsMenu(@NonNull Menu menu) { for (RouterTransaction transaction : backstack) { - transaction.controller.prepareOptionsMenu(menu); + transaction.controller().prepareOptionsMenu(menu); - for (Router childRouter : transaction.controller.getChildRouters()) { + for (Router childRouter : transaction.controller().getChildRouters()) { childRouter.onPrepareOptionsMenu(menu); } } @@ -684,11 +683,11 @@ public abstract class Router { public final boolean onOptionsItemSelected(@NonNull MenuItem item) { for (RouterTransaction transaction : backstack) { - if (transaction.controller.optionsItemSelected(item)) { + if (transaction.controller().optionsItemSelected(item)) { return true; } - for (Router childRouter : transaction.controller.getChildRouters()) { + for (Router childRouter : transaction.controller().getChildRouters()) { if (childRouter.onOptionsItemSelected(item)) { return true; } @@ -721,12 +720,7 @@ public abstract class Router { } void watchContainerAttach() { - container.post(new Runnable() { - @Override - public void run() { - containerFullyAttached = true; - } - }); + container.post(() -> containerFullyAttached = true); } void prepareForContainerRemoval() { @@ -739,7 +733,7 @@ public abstract class Router { void onContextAvailable() { for (RouterTransaction transaction : backstack) { - transaction.controller.onContextAvailable(); + transaction.controller().onContextAvailable(); } } @@ -749,7 +743,7 @@ public abstract class Router { Iterator backstackIterator = backstack.reverseIterator(); while (backstackIterator.hasNext()) { - controllers.add(backstackIterator.next().controller); + controllers.add(backstackIterator.next().controller()); } return controllers; @@ -758,8 +752,8 @@ public abstract class Router { @Nullable public final Boolean handleRequestedPermission(@NonNull String permission) { for (RouterTransaction transaction : backstack) { - if (transaction.controller.didRequestPermission(permission)) { - return transaction.controller.shouldShowRequestPermissionRationale(permission); + if (transaction.controller().didRequestPermission(permission)) { + return transaction.controller().shouldShowRequestPermissionRationale(permission); } } return null; @@ -784,8 +778,8 @@ public abstract class Router { } private void performControllerChange(@Nullable RouterTransaction to, @Nullable RouterTransaction from, boolean isPush, @Nullable ControllerChangeHandler changeHandler) { - Controller toController = to != null ? to.controller : null; - Controller fromController = from != null ? from.controller : null; + Controller toController = to != null ? to.controller() : null; + Controller fromController = from != null ? from.controller() : null; boolean forceDetachDestroy = false; if (to != null) { @@ -808,7 +802,7 @@ public abstract class Router { if (fromController.getView() != null) { fromController.detach(fromController.getView(), true, false); } else { - fromController.destroy(); + from.controller().destroy(); } } } @@ -835,12 +829,7 @@ public abstract class Router { to.setNeedsAttach(true); } pendingControllerChanges.add(transaction); - container.post(new Runnable() { - @Override - public void run() { - performPendingControllerChanges(); - } - }); + container.post(this::performPendingControllerChanges); } else { ControllerChangeHandler.executeChange(transaction); } @@ -856,17 +845,17 @@ public abstract class Router { } protected void pushToBackstack(@NonNull RouterTransaction entry) { - if (backstack.contains(entry.controller)) { + if (backstack.contains(entry.controller())) { throw new IllegalStateException("Trying to push a controller that already exists on the backstack."); } backstack.push(entry); } private void trackDestroyingController(@NonNull RouterTransaction transaction) { - if (!transaction.controller.isDestroyed()) { - destroyingControllers.add(transaction.controller); + if (!transaction.controller().isDestroyed()) { + destroyingControllers.add(transaction.controller()); - transaction.controller.addLifecycleListener(new LifecycleListener() { + transaction.controller().addLifecycleListener(new Controller.LifecycleListener() { @Override public void postDestroy(@NonNull Controller controller) { destroyingControllers.remove(controller); @@ -885,8 +874,8 @@ public abstract class Router { List views = new ArrayList<>(); for (RouterTransaction transaction : getVisibleTransactions(backstack.iterator())) { - if (transaction.controller.getView() != null) { - views.add(transaction.controller.getView()); + if (transaction.controller().getView() != null) { + views.add(transaction.controller().getView()); } } @@ -911,21 +900,21 @@ public abstract class Router { List indices = new ArrayList<>(backstack.size()); for (RouterTransaction transaction : backstack) { transaction.ensureValidIndex(getTransactionIndexer()); - indices.add(transaction.transactionIndex); + indices.add(transaction.getTransactionIndex()); } Collections.sort(indices); for (int i = 0; i < backstack.size(); i++) { - backstack.get(i).transactionIndex = indices.get(i); + backstack.get(i).setTransactionIndex(indices.get(i)); } } private void ensureNoDuplicateControllers(List backstack) { for (int i = 0; i < backstack.size(); i++) { - Controller controller = backstack.get(i).controller; + Controller controller = backstack.get(i).controller(); for (int j = i + 1; j < backstack.size(); j++) { - if (backstack.get(j).controller == controller) { + if (backstack.get(j).controller() == controller) { throw new IllegalStateException("Trying to push the same controller to the backstack more than once."); } } diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/RouterTransaction.java b/conductor/src/main/java/com/bluelinelabs/conductor/RouterTransaction.java deleted file mode 100644 index 57b59ed..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/RouterTransaction.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.bluelinelabs.conductor; - -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.bluelinelabs.conductor.internal.TransactionIndexer; - -/** - * Metadata used for adding {@link Controller}s to a {@link Router}. - */ -public class RouterTransaction { - - private static int INVALID_INDEX = -1; - - private static final String KEY_VIEW_CONTROLLER_BUNDLE = "RouterTransaction.controller.bundle"; - private static final String KEY_PUSH_TRANSITION = "RouterTransaction.pushControllerChangeHandler"; - private static final String KEY_POP_TRANSITION = "RouterTransaction.popControllerChangeHandler"; - private static final String KEY_TAG = "RouterTransaction.tag"; - private static final String KEY_INDEX = "RouterTransaction.transactionIndex"; - private static final String KEY_ATTACHED_TO_ROUTER = "RouterTransaction.attachedToRouter"; - - @NonNull final Controller controller; - private String tag; - - private ControllerChangeHandler pushControllerChangeHandler; - private ControllerChangeHandler popControllerChangeHandler; - private boolean attachedToRouter; - int transactionIndex = INVALID_INDEX; - - @NonNull - public static RouterTransaction with(@NonNull Controller controller) { - return new RouterTransaction(controller); - } - - private RouterTransaction(@NonNull Controller controller) { - this.controller = controller; - } - - RouterTransaction(@NonNull Bundle bundle) { - controller = Controller.newInstance(bundle.getBundle(KEY_VIEW_CONTROLLER_BUNDLE)); - pushControllerChangeHandler = ControllerChangeHandler.fromBundle(bundle.getBundle(KEY_PUSH_TRANSITION)); - popControllerChangeHandler = ControllerChangeHandler.fromBundle(bundle.getBundle(KEY_POP_TRANSITION)); - tag = bundle.getString(KEY_TAG); - transactionIndex = bundle.getInt(KEY_INDEX); - attachedToRouter = bundle.getBoolean(KEY_ATTACHED_TO_ROUTER); - } - - void onAttachedToRouter() { - attachedToRouter = true; - } - - @NonNull - public Controller controller() { - return controller; - } - - @Nullable - public String tag() { - return tag; - } - - @NonNull - public RouterTransaction tag(@Nullable String tag) { - if (!attachedToRouter) { - this.tag = tag; - return this; - } else { - throw new RuntimeException(getClass().getSimpleName() + "s can not be modified after being added to a Router."); - } - } - - @Nullable - public ControllerChangeHandler pushChangeHandler() { - ControllerChangeHandler handler = controller.getOverriddenPushHandler(); - if (handler == null) { - handler = pushControllerChangeHandler; - } - return handler; - } - - @NonNull - public RouterTransaction pushChangeHandler(@Nullable ControllerChangeHandler handler) { - if (!attachedToRouter) { - pushControllerChangeHandler = handler; - return this; - } else { - throw new RuntimeException(getClass().getSimpleName() + "s can not be modified after being added to a Router."); - } - } - - @Nullable - public ControllerChangeHandler popChangeHandler() { - ControllerChangeHandler handler = controller.getOverriddenPopHandler(); - if (handler == null) { - handler = popControllerChangeHandler; - } - return handler; - } - - @NonNull - public RouterTransaction popChangeHandler(@Nullable ControllerChangeHandler handler) { - if (!attachedToRouter) { - popControllerChangeHandler = handler; - return this; - } else { - throw new RuntimeException(getClass().getSimpleName() + "s can not be modified after being added to a Router."); - } - } - - void ensureValidIndex(@NonNull TransactionIndexer indexer) { - if (transactionIndex == INVALID_INDEX) { - transactionIndex = indexer.nextIndex(); - } - } - - /** - * Used to serialize this transaction into a Bundle - */ - @NonNull - public Bundle saveInstanceState() { - Bundle bundle = new Bundle(); - - bundle.putBundle(KEY_VIEW_CONTROLLER_BUNDLE, controller.saveInstanceState()); - - if (pushControllerChangeHandler != null) { - bundle.putBundle(KEY_PUSH_TRANSITION, pushControllerChangeHandler.toBundle()); - } - if (popControllerChangeHandler != null) { - bundle.putBundle(KEY_POP_TRANSITION, popControllerChangeHandler.toBundle()); - } - - bundle.putString(KEY_TAG, tag); - bundle.putInt(KEY_INDEX, transactionIndex); - bundle.putBoolean(KEY_ATTACHED_TO_ROUTER, attachedToRouter); - - return bundle; - } - -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/RouterTransaction.kt b/conductor/src/main/java/com/bluelinelabs/conductor/RouterTransaction.kt new file mode 100644 index 0000000..2b7fd71 --- /dev/null +++ b/conductor/src/main/java/com/bluelinelabs/conductor/RouterTransaction.kt @@ -0,0 +1,123 @@ +package com.bluelinelabs.conductor + +import android.os.Bundle +import androidx.annotation.RestrictTo +import androidx.annotation.RestrictTo.Scope.LIBRARY +import com.bluelinelabs.conductor.internal.TransactionIndexer + +private const val INVALID_INDEX = -1 +private const val KEY_VIEW_CONTROLLER_BUNDLE = "RouterTransaction.controller.bundle" +private const val KEY_PUSH_TRANSITION = "RouterTransaction.pushControllerChangeHandler" +private const val KEY_POP_TRANSITION = "RouterTransaction.popControllerChangeHandler" +private const val KEY_TAG = "RouterTransaction.tag" +private const val KEY_INDEX = "RouterTransaction.transactionIndex" +private const val KEY_ATTACHED_TO_ROUTER = "RouterTransaction.attachedToRouter" + +/** + * Metadata used for adding [Controller]s to a [Router]. + */ +class RouterTransaction +private constructor( + @get:JvmName("controller") + val controller: Controller, + private var tag: String? = null, + private var pushControllerChangeHandler: ControllerChangeHandler? = null, + private var popControllerChangeHandler: ControllerChangeHandler? = null, + private var attachedToRouter: Boolean = false, + @RestrictTo(LIBRARY) + var transactionIndex: Int = INVALID_INDEX +) { + + + @RestrictTo(LIBRARY) + internal constructor(bundle: Bundle) : this( + controller = Controller.newInstance(bundle.getBundle(KEY_VIEW_CONTROLLER_BUNDLE)!!), + pushControllerChangeHandler = ControllerChangeHandler.fromBundle( + bundle.getBundle( + KEY_PUSH_TRANSITION + ) + ), + popControllerChangeHandler = ControllerChangeHandler.fromBundle( + bundle.getBundle( + KEY_POP_TRANSITION + ) + ), + tag = bundle.getString(KEY_TAG), + transactionIndex = bundle.getInt(KEY_INDEX), + attachedToRouter = bundle.getBoolean(KEY_ATTACHED_TO_ROUTER) + ) + + fun onAttachedToRouter() { + attachedToRouter = true + } + + fun tag(): String? = tag + + fun tag(tag: String?): RouterTransaction { + return if (!attachedToRouter) { + this.tag = tag + this + } else { + throw RuntimeException(javaClass.simpleName + "s can not be modified after being added to a Router.") + } + } + + fun pushChangeHandler(): ControllerChangeHandler? { + return controller.overriddenPushHandler ?: pushControllerChangeHandler + } + + fun pushChangeHandler(handler: ControllerChangeHandler?): RouterTransaction { + return if (!attachedToRouter) { + pushControllerChangeHandler = handler + this + } else { + throw RuntimeException("${javaClass.simpleName}s can not be modified after being added to a Router.") + } + } + + fun popChangeHandler(): ControllerChangeHandler? { + return controller.overriddenPopHandler ?: popControllerChangeHandler + } + + fun popChangeHandler(handler: ControllerChangeHandler?): RouterTransaction { + return if (!attachedToRouter) { + popControllerChangeHandler = handler + this + } else { + throw RuntimeException("${javaClass.simpleName}s can not be modified after being added to a Router.") + } + } + + fun ensureValidIndex(indexer: TransactionIndexer) { + if (transactionIndex == INVALID_INDEX) { + transactionIndex = indexer.nextIndex() + } + } + + /** + * Used to serialize this transaction into a Bundle + */ + fun saveInstanceState(): Bundle = Bundle().apply { + putBundle(KEY_VIEW_CONTROLLER_BUNDLE, controller.saveInstanceState()) + pushControllerChangeHandler?.let { putBundle(KEY_PUSH_TRANSITION, it.toBundle()) } + popControllerChangeHandler?.let { putBundle(KEY_POP_TRANSITION, it.toBundle()) } + putString(KEY_TAG, tag) + putInt(KEY_INDEX, transactionIndex) + putBoolean(KEY_ATTACHED_TO_ROUTER, attachedToRouter) + } + + companion object { + + @JvmStatic + fun with(controller: Controller): RouterTransaction = RouterTransaction(controller) + } +} + +fun Controller.asTransaction( + popChangeHandler: ControllerChangeHandler? = null, + pushChangeHandler: ControllerChangeHandler? = null +): RouterTransaction { + return RouterTransaction.with(this) + .pushChangeHandler(pushChangeHandler) + .popChangeHandler(popChangeHandler) +} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/SharedElementTransitionChangeHandler.java b/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/SharedElementTransitionChangeHandler.java index 6501e7f..7ff26d1 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/SharedElementTransitionChangeHandler.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/SharedElementTransitionChangeHandler.java @@ -13,6 +13,9 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnPreDrawListener; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.bluelinelabs.conductor.Controller; import com.bluelinelabs.conductor.ControllerChangeHandler; import com.bluelinelabs.conductor.internal.LegacyTransitionUtils; @@ -20,9 +23,6 @@ import com.bluelinelabs.conductor.internal.LegacyTransitionUtils; import java.util.ArrayList; import java.util.List; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - /** * A TransitionChangeHandler that facilitates using different Transitions for the entering view, the exiting view, * and shared elements between the two. @@ -64,12 +64,9 @@ public abstract class SharedElementTransitionChangeHandler extends TransitionCha @Override public void prepareForTransition(@NonNull final ViewGroup container, @Nullable final View from, @Nullable final View to, @NonNull final Transition transition, final boolean isPush, @NonNull final OnTransitionPreparedListener onTransitionPreparedListener) { - OnTransitionPreparedListener listener = new OnTransitionPreparedListener() { - @Override - public void onPrepared() { - configureTransition(container, from, to, transition, isPush); - onTransitionPreparedListener.onPrepared(); - } + OnTransitionPreparedListener listener = () -> { + configureTransition(container, from, to, transition, isPush); + onTransitionPreparedListener.onPrepared(); }; configureSharedElements(container, from, to, isPush); @@ -168,19 +165,16 @@ public abstract class SharedElementTransitionChangeHandler extends TransitionCha void waitOnChildTransitionNames(@NonNull final View to, @NonNull List foundViews, @NonNull final OnPreDrawListener parentPreDrawListener, @NonNull final OnTransitionPreparedListener onTransitionPreparedListener) { for (final View view : foundViews) { - OneShotPreDrawListener.add(true, view, new Runnable() { - @Override - public void run() { - waitForTransitionNames.remove(view.getTransitionName()); + OneShotPreDrawListener.add(true, view, () -> { + waitForTransitionNames.remove(view.getTransitionName()); - removedViews.add(new ViewParentPair(view, (ViewGroup)view.getParent())); - ((ViewGroup)view.getParent()).removeView(view); + removedViews.add(new ViewParentPair(view, (ViewGroup) view.getParent())); + ((ViewGroup) view.getParent()).removeView(view); - if (waitForTransitionNames.size() == 0) { - to.getViewTreeObserver().removeOnPreDrawListener(parentPreDrawListener); - to.setVisibility(View.INVISIBLE); - onTransitionPreparedListener.onPrepared(); - } + if (waitForTransitionNames.size() == 0) { + to.getViewTreeObserver().removeOnPreDrawListener(parentPreDrawListener); + to.setVisibility(View.INVISIBLE); + onTransitionPreparedListener.onPrepared(); } }); } @@ -188,24 +182,21 @@ public abstract class SharedElementTransitionChangeHandler extends TransitionCha private void scheduleTargetChange(@NonNull final ViewGroup container, @Nullable final View to, @NonNull final View nonExistentView, @NonNull final List toSharedElements, @NonNull final List enteringViews, @Nullable final List exitingViews) { - OneShotPreDrawListener.add(true, container, new Runnable() { - @Override - public void run() { - if (enterTransition != null) { - enterTransition.removeTarget(nonExistentView); - List views = configureEnteringExitingViews(enterTransition, to, toSharedElements, nonExistentView); - enteringViews.addAll(views); - } + OneShotPreDrawListener.add(true, container, () -> { + if (enterTransition != null) { + enterTransition.removeTarget(nonExistentView); + List views = configureEnteringExitingViews(enterTransition, to, toSharedElements, nonExistentView); + enteringViews.addAll(views); + } - if (exitingViews != null) { - if (exitTransition != null) { - List tempExiting = new ArrayList<>(); - tempExiting.add(nonExistentView); - LegacyTransitionUtils.replaceTargets(exitTransition, exitingViews, tempExiting); - } - exitingViews.clear(); - exitingViews.add(nonExistentView); + if (exitingViews != null) { + if (exitTransition != null) { + List tempExiting = new ArrayList<>(); + tempExiting.add(nonExistentView); + LegacyTransitionUtils.replaceTargets(exitTransition, exitingViews, tempExiting); } + exitingViews.clear(); + exitingViews.add(nonExistentView); } }); } @@ -275,26 +266,23 @@ public abstract class SharedElementTransitionChangeHandler extends TransitionCha toEpicenter = null; } - OneShotPreDrawListener.add(true, container, new Runnable() { - @Override - public void run() { - ArrayMap capturedToSharedElements = captureToSharedElements(to, isPush); + OneShotPreDrawListener.add(true, container, () -> { + ArrayMap capturedToSharedElements = captureToSharedElements(to, isPush); - if (capturedToSharedElements != null) { - toSharedElements.addAll(capturedToSharedElements.values()); - toSharedElements.add(nonExistentView); - } + if (capturedToSharedElements != null) { + toSharedElements.addAll(capturedToSharedElements.values()); + toSharedElements.add(nonExistentView); + } - callSharedElementStartEnd(capturedToSharedElements, false); - if (sharedElementTransition != null) { - sharedElementTransition.getTargets().clear(); - sharedElementTransition.getTargets().addAll(toSharedElements); - LegacyTransitionUtils.replaceTargets(sharedElementTransition, fromSharedElements, toSharedElements); + callSharedElementStartEnd(capturedToSharedElements, false); + if (sharedElementTransition != null) { + sharedElementTransition.getTargets().clear(); + sharedElementTransition.getTargets().addAll(toSharedElements); + LegacyTransitionUtils.replaceTargets(sharedElementTransition, fromSharedElements, toSharedElements); - final View toEpicenterView = getToEpicenterView(capturedToSharedElements); - if (toEpicenterView != null && toEpicenter != null) { - LegacyTransitionUtils.getBoundsOnScreen(toEpicenterView, toEpicenter); - } + final View toEpicenterView = getToEpicenterView(capturedToSharedElements); + if (toEpicenterView != null && toEpicenter != null) { + LegacyTransitionUtils.getBoundsOnScreen(toEpicenterView, toEpicenter); } } }); @@ -474,33 +462,27 @@ public abstract class SharedElementTransitionChangeHandler extends TransitionCha } private void setNameOverrides(@NonNull final View container, @NonNull final List toSharedElements) { - OneShotPreDrawListener.add(true, container, new Runnable() { - @Override - public void run() { - final int numSharedElements = toSharedElements.size(); - for (int i = 0; i < numSharedElements; i++) { - View view = toSharedElements.get(i); - String name = view.getTransitionName(); - if (name != null) { - String inName = findKeyForValue(sharedElementNames, name); - view.setTransitionName(inName); - } + OneShotPreDrawListener.add(true, container, () -> { + final int numSharedElements = toSharedElements.size(); + for (int i = 0; i < numSharedElements; i++) { + View view = toSharedElements.get(i); + String name = view.getTransitionName(); + if (name != null) { + String inName = findKeyForValue(sharedElementNames, name); + view.setTransitionName(inName); } } }); } private void scheduleNameReset(@NonNull final ViewGroup container, @NonNull final List toSharedElements) { - OneShotPreDrawListener.add(true, container, new Runnable() { - @Override - public void run() { - final int numSharedElements = toSharedElements.size(); - for (int i = 0; i < numSharedElements; i++) { - final View view = toSharedElements.get(i); - final String name = view.getTransitionName(); - final String inName = sharedElementNames.get(name); - view.setTransitionName(inName); - } + OneShotPreDrawListener.add(true, container, () -> { + final int numSharedElements = toSharedElements.size(); + for (int i = 0; i < numSharedElements; i++) { + final View view = toSharedElements.get(i); + final String name = view.getTransitionName(); + final String inName = sharedElementNames.get(name); + view.setTransitionName(inName); } }); } diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandler.java b/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandler.java index 30f245a..db10825 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandler.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/changehandler/TransitionChangeHandler.java @@ -2,14 +2,15 @@ package com.bluelinelabs.conductor.changehandler; import android.annotation.TargetApi; import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import android.transition.Transition; import android.transition.Transition.TransitionListener; import android.transition.TransitionManager; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.bluelinelabs.conductor.Controller; import com.bluelinelabs.conductor.ControllerChangeHandler; @@ -74,12 +75,7 @@ public abstract class TransitionChangeHandler extends ControllerChangeHandler { return; } - final Runnable onTransitionNotStarted = new Runnable() { - @Override - public void run() { - changeListener.onChangeCompleted(); - } - }; + final Runnable onTransitionNotStarted = changeListener::onChangeCompleted; final Transition transition = getTransition(container, from, to, isPush); transition.addListener(new TransitionListener() { @@ -107,14 +103,11 @@ public abstract class TransitionChangeHandler extends ControllerChangeHandler { public void onTransitionResume(Transition transition) { } }); - prepareForTransition(container, from, to, transition, isPush, new OnTransitionPreparedListener() { - @Override - public void onPrepared() { - if (!canceled) { - TransitionManager.beginDelayedTransition(container, transition); - executePropertyChanges(container, from, to, transition, isPush); - container.post(onTransitionNotStarted); - } + prepareForTransition(container, from, to, transition, isPush, () -> { + if (!canceled) { + TransitionManager.beginDelayedTransition(container, transition); + executePropertyChanges(container, from, to, transition, isPush); + container.post(onTransitionNotStarted); } }); } diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/LifecycleHandler.java b/conductor/src/main/java/com/bluelinelabs/conductor/internal/LifecycleHandler.java index c54ce83..44face9 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/internal/LifecycleHandler.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/internal/LifecycleHandler.java @@ -17,6 +17,9 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.bluelinelabs.conductor.ActivityHostedRouter; import com.bluelinelabs.conductor.Router; @@ -25,9 +28,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - public class LifecycleHandler extends Fragment implements ActivityLifecycleCallbacks { private static final String FRAGMENT_TAG = "LifecycleHandler"; @@ -101,7 +101,7 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb @NonNull public List getRouters() { - return new ArrayList(routerMap.values()); + return new ArrayList<>(routerMap.values()); } @Nullable @@ -133,13 +133,13 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb if (savedInstanceState != null) { StringSparseArrayParceler permissionParcel = savedInstanceState.getParcelable(KEY_PERMISSION_REQUEST_CODES); - permissionRequestMap = permissionParcel != null ? permissionParcel.getStringSparseArray() : new SparseArray(); + permissionRequestMap = permissionParcel != null ? permissionParcel.getStringSparseArray() : new SparseArray<>(); StringSparseArrayParceler activityParcel = savedInstanceState.getParcelable(KEY_ACTIVITY_REQUEST_CODES); - activityRequestMap = activityParcel != null ? activityParcel.getStringSparseArray() : new SparseArray(); + activityRequestMap = activityParcel != null ? activityParcel.getStringSparseArray() : new SparseArray<>(); ArrayList pendingRequests = savedInstanceState.getParcelableArrayList(KEY_PENDING_PERMISSION_REQUESTS); - pendingPermissionRequests = pendingRequests != null ? pendingRequests : new ArrayList(); + pendingPermissionRequests = pendingRequests != null ? pendingRequests : new ArrayList<>(); } } @@ -164,7 +164,6 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb } } - @SuppressWarnings("deprecation") @Override public void onAttach(Activity activity) { super.onAttach(activity); diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/NoOpControllerChangeHandler.java b/conductor/src/main/java/com/bluelinelabs/conductor/internal/NoOpControllerChangeHandler.java deleted file mode 100644 index d06425e..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/internal/NoOpControllerChangeHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.bluelinelabs.conductor.internal; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.bluelinelabs.conductor.ControllerChangeHandler; - -public class NoOpControllerChangeHandler extends ControllerChangeHandler { - - @Override - public void performChange(@NonNull ViewGroup container, @Nullable View from, @Nullable View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) { - changeListener.onChangeCompleted(); - } - - @NonNull - @Override - public ControllerChangeHandler copy() { - return new NoOpControllerChangeHandler(); - } - - @Override - public boolean isReusable() { - return true; - } -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/NoOpControllerChangeHandler.kt b/conductor/src/main/java/com/bluelinelabs/conductor/internal/NoOpControllerChangeHandler.kt new file mode 100644 index 0000000..ddb0184 --- /dev/null +++ b/conductor/src/main/java/com/bluelinelabs/conductor/internal/NoOpControllerChangeHandler.kt @@ -0,0 +1,22 @@ +package com.bluelinelabs.conductor.internal + +import android.view.View +import android.view.ViewGroup +import com.bluelinelabs.conductor.ControllerChangeHandler + +class NoOpControllerChangeHandler : ControllerChangeHandler() { + + override fun performChange( + container: ViewGroup, + from: View?, + to: View?, + isPush: Boolean, + changeListener: ControllerChangeCompletedListener + ) { + changeListener.onChangeCompleted() + } + + override fun copy(): ControllerChangeHandler = NoOpControllerChangeHandler() + + override fun isReusable() = true +} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/RouterRequiringFunc.java b/conductor/src/main/java/com/bluelinelabs/conductor/internal/RouterRequiringFunc.java deleted file mode 100644 index 7de087d..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/internal/RouterRequiringFunc.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.bluelinelabs.conductor.internal; - -public interface RouterRequiringFunc { - void execute(); -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/RouterRequiringFunc.kt b/conductor/src/main/java/com/bluelinelabs/conductor/internal/RouterRequiringFunc.kt new file mode 100644 index 0000000..9954771 --- /dev/null +++ b/conductor/src/main/java/com/bluelinelabs/conductor/internal/RouterRequiringFunc.kt @@ -0,0 +1,9 @@ +package com.bluelinelabs.conductor.internal + +import androidx.annotation.RestrictTo +import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP + +@RestrictTo(LIBRARY_GROUP) +interface RouterRequiringFunc { + fun execute() +} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/ThreadUtils.java b/conductor/src/main/java/com/bluelinelabs/conductor/internal/ThreadUtils.java deleted file mode 100644 index 172023f..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/internal/ThreadUtils.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.bluelinelabs.conductor.internal; - -import android.os.Looper; -import android.util.AndroidRuntimeException; - -public class ThreadUtils { - - public static void ensureMainThread() { - if (Looper.getMainLooper().getThread() != Thread.currentThread()) { - throw new CalledFromWrongThreadException("Methods that affect the view hierarchy can can only be called from the main thread."); - } - } - - private static final class CalledFromWrongThreadException extends AndroidRuntimeException { - CalledFromWrongThreadException(String msg) { - super(msg); - } - } - -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/ThreadUtils.kt b/conductor/src/main/java/com/bluelinelabs/conductor/internal/ThreadUtils.kt new file mode 100644 index 0000000..83b0965 --- /dev/null +++ b/conductor/src/main/java/com/bluelinelabs/conductor/internal/ThreadUtils.kt @@ -0,0 +1,17 @@ +@file:JvmName("ThreadUtils") + +package com.bluelinelabs.conductor.internal + +import android.os.Looper +import android.util.AndroidRuntimeException +import androidx.annotation.RestrictTo +import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP + +@RestrictTo(LIBRARY_GROUP) +internal fun ensureMainThread() { + if (Looper.getMainLooper().thread !== Thread.currentThread()) { + throw CalledFromWrongThreadException("Methods that affect the view hierarchy can can only be called from the main thread.") + } +} + +private class CalledFromWrongThreadException(msg: String?) : AndroidRuntimeException(msg) diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/TransactionIndexer.java b/conductor/src/main/java/com/bluelinelabs/conductor/internal/TransactionIndexer.java deleted file mode 100644 index 232c7f7..0000000 --- a/conductor/src/main/java/com/bluelinelabs/conductor/internal/TransactionIndexer.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.bluelinelabs.conductor.internal; - -import android.os.Bundle; -import androidx.annotation.NonNull; - -public class TransactionIndexer { - - private static final String KEY_INDEX = "TransactionIndexer.currentIndex"; - - private int currentIndex; - - public int nextIndex() { - return ++currentIndex; - } - - public void saveInstanceState(@NonNull Bundle outState) { - outState.putInt(KEY_INDEX, currentIndex); - } - - public void restoreInstanceState(@NonNull Bundle savedInstanceState) { - currentIndex = savedInstanceState.getInt(KEY_INDEX); - } - -} diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/TransactionIndexer.kt b/conductor/src/main/java/com/bluelinelabs/conductor/internal/TransactionIndexer.kt new file mode 100644 index 0000000..344bdaa --- /dev/null +++ b/conductor/src/main/java/com/bluelinelabs/conductor/internal/TransactionIndexer.kt @@ -0,0 +1,25 @@ +package com.bluelinelabs.conductor.internal + +import android.os.Bundle +import androidx.annotation.RestrictTo +import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP + +@RestrictTo(LIBRARY_GROUP) +class TransactionIndexer { + + private var currentIndex = 0 + + fun nextIndex(): Int { + return ++currentIndex + } + + fun saveInstanceState(outState: Bundle) { + outState.putInt(KEY_INDEX, currentIndex) + } + + fun restoreInstanceState(savedInstanceState: Bundle) { + currentIndex = savedInstanceState.getInt(KEY_INDEX) + } +} + +private const val KEY_INDEX = "TransactionIndexer.currentIndex" diff --git a/conductor/src/main/java/com/bluelinelabs/conductor/internal/ViewAttachHandler.java b/conductor/src/main/java/com/bluelinelabs/conductor/internal/ViewAttachHandler.java index fbb3f72..06425bb 100644 --- a/conductor/src/main/java/com/bluelinelabs/conductor/internal/ViewAttachHandler.java +++ b/conductor/src/main/java/com/bluelinelabs/conductor/internal/ViewAttachHandler.java @@ -40,13 +40,10 @@ public class ViewAttachHandler implements OnAttachStateChangeListener { } rootAttached = true; - listenForDeepestChildAttach(v, new ChildAttachListener() { - @Override - public void onAttached() { - childrenAttached = true; - reportAttached(); + listenForDeepestChildAttach(v, () -> { + childrenAttached = true; + reportAttached(); - } }); } diff --git a/conductor/src/test/java/com/bluelinelabs/conductor/ControllerLifecycleActivityReferenceTests.java b/conductor/src/test/java/com/bluelinelabs/conductor/ControllerLifecycleActivityReferenceTests.java index 651e3e6..dcc3132 100644 --- a/conductor/src/test/java/com/bluelinelabs/conductor/ControllerLifecycleActivityReferenceTests.java +++ b/conductor/src/test/java/com/bluelinelabs/conductor/ControllerLifecycleActivityReferenceTests.java @@ -1,9 +1,9 @@ package com.bluelinelabs.conductor; import android.os.Bundle; -import androidx.annotation.NonNull; import android.view.View; -import android.view.ViewGroup; + +import androidx.annotation.NonNull; import com.bluelinelabs.conductor.util.ActivityProxy; import com.bluelinelabs.conductor.util.MockChangeHandler; @@ -85,7 +85,7 @@ public class ControllerLifecycleActivityReferenceTests { ActivityReferencingLifecycleListener listener = new ActivityReferencingLifecycleListener(); child.addLifecycleListener(listener); - Router childRouter = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID)); + Router childRouter = parent.getChildRouter(parent.getView().findViewById(TestController.VIEW_ID)); childRouter.pushController(RouterTransaction.with(child) .pushChangeHandler(MockChangeHandler.defaultHandler()) .popChangeHandler(MockChangeHandler.defaultHandler())); @@ -132,7 +132,7 @@ public class ControllerLifecycleActivityReferenceTests { ActivityReferencingLifecycleListener listener = new ActivityReferencingLifecycleListener(); child.addLifecycleListener(listener); - Router childRouter = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID)); + Router childRouter = parent.getChildRouter(parent.getView().findViewById(TestController.VIEW_ID)); childRouter.setPopsLastView(true); childRouter.pushController(RouterTransaction.with(child) .pushChangeHandler(MockChangeHandler.defaultHandler()) @@ -161,7 +161,7 @@ public class ControllerLifecycleActivityReferenceTests { ActivityReferencingLifecycleListener listener = new ActivityReferencingLifecycleListener(); child.addLifecycleListener(listener); - Router childRouter = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID)); + Router childRouter = parent.getChildRouter(parent.getView().findViewById(TestController.VIEW_ID)); childRouter.setPopsLastView(true); childRouter.pushController(RouterTransaction.with(child) .pushChangeHandler(MockChangeHandler.defaultHandler()) @@ -211,7 +211,7 @@ public class ControllerLifecycleActivityReferenceTests { ActivityReferencingLifecycleListener listener = new ActivityReferencingLifecycleListener(); child.addLifecycleListener(listener); - Router childRouter = parent.getChildRouter((ViewGroup)parent.getView().findViewById(TestController.VIEW_ID)); + Router childRouter = parent.getChildRouter(parent.getView().findViewById(TestController.VIEW_ID)); childRouter.setPopsLastView(true); childRouter.pushController(RouterTransaction.with(child) .pushChangeHandler(MockChangeHandler.defaultHandler()) @@ -227,7 +227,7 @@ public class ControllerLifecycleActivityReferenceTests { assertEquals(Collections.singletonList(true), listener.postDestroyReferences); } - static class ActivityReferencingLifecycleListener extends Controller.LifecycleListener { + static class ActivityReferencingLifecycleListener implements Controller.LifecycleListener { final List changeEndReferences = new ArrayList<>(); final List postCreateViewReferences = new ArrayList<>(); final List postAttachReferences = new ArrayList<>(); diff --git a/conductor/src/test/java/com/bluelinelabs/conductor/ControllerTests.java b/conductor/src/test/java/com/bluelinelabs/conductor/ControllerTests.java index 25d5121..81f339a 100644 --- a/conductor/src/test/java/com/bluelinelabs/conductor/ControllerTests.java +++ b/conductor/src/test/java/com/bluelinelabs/conductor/ControllerTests.java @@ -392,10 +392,10 @@ public class ControllerTests { RouterTransaction restoredChildTransaction1 = childRouter.getBackstack().get(0); RouterTransaction restoredChildTransaction2 = childRouter.getBackstack().get(1); - assertEquals(childTransaction1.transactionIndex, restoredChildTransaction1.transactionIndex); - assertEquals(childTransaction1.controller.getInstanceId(), restoredChildTransaction1.controller.getInstanceId()); - assertEquals(childTransaction2.transactionIndex, restoredChildTransaction2.transactionIndex); - assertEquals(childTransaction2.controller.getInstanceId(), restoredChildTransaction2.controller.getInstanceId()); + assertEquals(childTransaction1.getTransactionIndex(), restoredChildTransaction1.getTransactionIndex()); + assertEquals(childTransaction1.controller().getInstanceId(), restoredChildTransaction1.controller().getInstanceId()); + assertEquals(childTransaction2.getTransactionIndex(), restoredChildTransaction2.getTransactionIndex()); + assertEquals(childTransaction2.controller().getInstanceId(), restoredChildTransaction2.controller().getInstanceId()); assertTrue(parent.handleBack()); assertEquals(1, childRouter.getBackstackSize()); diff --git a/conductor/src/test/java/com/bluelinelabs/conductor/ControllerTransactionTests.java b/conductor/src/test/java/com/bluelinelabs/conductor/ControllerTransactionTests.java index 0716af4..8002907 100644 --- a/conductor/src/test/java/com/bluelinelabs/conductor/ControllerTransactionTests.java +++ b/conductor/src/test/java/com/bluelinelabs/conductor/ControllerTransactionTests.java @@ -26,7 +26,7 @@ public class ControllerTransactionTests { RouterTransaction restoredTransaction = new RouterTransaction(bundle); - assertEquals(transaction.controller.getClass(), restoredTransaction.controller.getClass()); + assertEquals(transaction.controller().getClass(), restoredTransaction.controller().getClass()); assertEquals(transaction.pushChangeHandler().getClass(), restoredTransaction.pushChangeHandler().getClass()); assertEquals(transaction.popChangeHandler().getClass(), restoredTransaction.popChangeHandler().getClass()); assertEquals(transaction.tag(), restoredTransaction.tag()); diff --git a/conductor/src/test/java/com/bluelinelabs/conductor/RouterTests.java b/conductor/src/test/java/com/bluelinelabs/conductor/RouterTests.java index 5b0062d..df4b062 100644 --- a/conductor/src/test/java/com/bluelinelabs/conductor/RouterTests.java +++ b/conductor/src/test/java/com/bluelinelabs/conductor/RouterTests.java @@ -1,9 +1,10 @@ package com.bluelinelabs.conductor; -import androidx.annotation.NonNull; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; + import com.bluelinelabs.conductor.Controller.LifecycleListener; import com.bluelinelabs.conductor.changehandler.FadeChangeHandler; import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler; @@ -250,9 +251,9 @@ public class RouterTests { assertEquals(middleTransaction, fetchedBackstack.get(1)); assertEquals(topTransaction, fetchedBackstack.get(2)); - assertEquals(router, rootTransaction.controller.getRouter()); - assertEquals(router, middleTransaction.controller.getRouter()); - assertEquals(router, topTransaction.controller.getRouter()); + assertEquals(router, rootTransaction.controller().getRouter()); + assertEquals(router, middleTransaction.controller().getRouter()); + assertEquals(router, topTransaction.controller().getRouter()); } @Test @@ -264,8 +265,8 @@ public class RouterTests { router.pushController(oldTopTransaction); assertEquals(2, router.getBackstackSize()); - assertTrue(oldRootTransaction.controller.isAttached()); - assertTrue(oldTopTransaction.controller.isAttached()); + assertTrue(oldRootTransaction.controller().isAttached()); + assertTrue(oldTopTransaction.controller().isAttached()); RouterTransaction rootTransaction = RouterTransaction.with(new TestController()); RouterTransaction middleTransaction = RouterTransaction.with(new TestController()).pushChangeHandler(MockChangeHandler.noRemoveViewOnPushHandler()); @@ -281,11 +282,11 @@ public class RouterTests { assertEquals(middleTransaction, fetchedBackstack.get(1)); assertEquals(topTransaction, fetchedBackstack.get(2)); - assertFalse(oldRootTransaction.controller.isAttached()); - assertFalse(oldTopTransaction.controller.isAttached()); - assertTrue(rootTransaction.controller.isAttached()); - assertTrue(middleTransaction.controller.isAttached()); - assertTrue(topTransaction.controller.isAttached()); + assertFalse(oldRootTransaction.controller().isAttached()); + assertFalse(oldTopTransaction.controller().isAttached()); + assertTrue(rootTransaction.controller().isAttached()); + assertTrue(middleTransaction.controller().isAttached()); + assertTrue(topTransaction.controller().isAttached()); } @Test @@ -304,9 +305,9 @@ public class RouterTests { assertEquals(1, router.getBackstackSize()); assertEquals(rootTransaction, router.getBackstack().get(0)); - assertTrue(rootTransaction.controller.isAttached()); - assertFalse(transaction1.controller.isAttached()); - assertFalse(transaction2.controller.isAttached()); + assertTrue(rootTransaction.controller().isAttached()); + assertFalse(transaction1.controller().isAttached()); + assertFalse(transaction2.controller().isAttached()); } @Test @@ -325,9 +326,9 @@ public class RouterTests { assertEquals(1, router.getBackstackSize()); assertEquals(rootTransaction, router.getBackstack().get(0)); - assertTrue(rootTransaction.controller.isAttached()); - assertFalse(transaction1.controller.isAttached()); - assertFalse(transaction2.controller.isAttached()); + assertTrue(rootTransaction.controller().isAttached()); + assertFalse(transaction1.controller().isAttached()); + assertFalse(transaction2.controller().isAttached()); } @Test @@ -364,8 +365,8 @@ public class RouterTests { assertEquals(2, router.getBackstackSize()); - assertTrue(rootTransaction.controller.isAttached()); - assertTrue(topTransaction.controller.isAttached()); + assertTrue(rootTransaction.controller().isAttached()); + assertTrue(topTransaction.controller().isAttached()); List fetchedBackstack = router.getBackstack(); assertEquals(rootTransaction, fetchedBackstack.get(0)); @@ -381,9 +382,9 @@ public class RouterTests { assertEquals(rootTransaction, fetchedBackstack.get(0)); assertEquals(newTopTransaction, fetchedBackstack.get(1)); - assertTrue(rootTransaction.controller.isAttached()); - assertFalse(topTransaction.controller.isAttached()); - assertTrue(newTopTransaction.controller.isAttached()); + assertTrue(rootTransaction.controller().isAttached()); + assertFalse(topTransaction.controller().isAttached()); + assertTrue(newTopTransaction.controller().isAttached()); } @Test @@ -394,14 +395,14 @@ public class RouterTests { List backstack = Arrays.asList(transaction1, transaction2); router.setBackstack(backstack, null); - assertEquals(1, transaction1.transactionIndex); - assertEquals(2, transaction2.transactionIndex); + assertEquals(1, transaction1.getTransactionIndex()); + assertEquals(2, transaction2.getTransactionIndex()); backstack = Arrays.asList(transaction2, transaction1); router.setBackstack(backstack, null); - assertEquals(1, transaction2.transactionIndex); - assertEquals(2, transaction1.transactionIndex); + assertEquals(1, transaction2.getTransactionIndex()); + assertEquals(2, transaction1.getTransactionIndex()); router.handleBack(); @@ -425,14 +426,14 @@ public class RouterTests { List backstack = Arrays.asList(transaction1, transaction2); childRouter.setBackstack(backstack, null); - assertEquals(2, transaction1.transactionIndex); - assertEquals(3, transaction2.transactionIndex); + assertEquals(2, transaction1.getTransactionIndex()); + assertEquals(3, transaction2.getTransactionIndex()); backstack = Arrays.asList(transaction2, transaction1); childRouter.setBackstack(backstack, null); - assertEquals(2, transaction2.transactionIndex); - assertEquals(3, transaction1.transactionIndex); + assertEquals(2, transaction2.getTransactionIndex()); + assertEquals(3, transaction1.getTransactionIndex()); childRouter.handleBack(); diff --git a/conductor/src/test/java/com/bluelinelabs/conductor/util/TestController.java b/conductor/src/test/java/com/bluelinelabs/conductor/util/TestController.java index 5175386..80bff1b 100644 --- a/conductor/src/test/java/com/bluelinelabs/conductor/util/TestController.java +++ b/conductor/src/test/java/com/bluelinelabs/conductor/util/TestController.java @@ -3,8 +3,6 @@ package com.bluelinelabs.conductor.util; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import androidx.annotation.IdRes; -import androidx.annotation.NonNull; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -12,6 +10,9 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; + import com.bluelinelabs.conductor.Controller; import com.bluelinelabs.conductor.ControllerChangeHandler; import com.bluelinelabs.conductor.ControllerChangeType; diff --git a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/ArchLifecycleController.java b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/ArchLifecycleController.java index 04b3ce1..5f99d1a 100644 --- a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/ArchLifecycleController.java +++ b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/ArchLifecycleController.java @@ -1,18 +1,19 @@ package com.bluelinelabs.conductor.demo.controllers; -import androidx.lifecycle.Lifecycle.Event; -import androidx.lifecycle.LifecycleObserver; -import androidx.lifecycle.LifecycleOwner; -import androidx.lifecycle.OnLifecycleEvent; import android.content.Context; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.lifecycle.Lifecycle.Event; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.OnLifecycleEvent; + import com.bluelinelabs.conductor.ControllerChangeHandler; import com.bluelinelabs.conductor.ControllerChangeType; import com.bluelinelabs.conductor.RouterTransaction; diff --git a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/AutodisposeController.java b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/AutodisposeController.java index 517fbfa..99d416b 100644 --- a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/AutodisposeController.java +++ b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/AutodisposeController.java @@ -1,13 +1,14 @@ package com.bluelinelabs.conductor.demo.controllers; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + import com.bluelinelabs.conductor.Controller; import com.bluelinelabs.conductor.ControllerChangeHandler; import com.bluelinelabs.conductor.ControllerChangeType; diff --git a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/ExternalModulesController.java b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/ExternalModulesController.java index 3236427..024fdf4 100644 --- a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/ExternalModulesController.java +++ b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/ExternalModulesController.java @@ -1,17 +1,18 @@ package com.bluelinelabs.conductor.demo.controllers; import android.graphics.PorterDuff.Mode; -import androidx.annotation.ColorRes; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import com.bluelinelabs.conductor.ControllerChangeHandler; import com.bluelinelabs.conductor.ControllerChangeType; import com.bluelinelabs.conductor.RouterTransaction; diff --git a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/HomeController.java b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/HomeController.java index 0a1bfc8..ad1a53e 100644 --- a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/HomeController.java +++ b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/HomeController.java @@ -4,12 +4,6 @@ import android.content.Intent; import android.graphics.PorterDuff.Mode; import android.net.Uri; import android.os.Bundle; -import androidx.annotation.ColorRes; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; -import androidx.core.view.ViewCompat; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -24,6 +18,13 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import com.bluelinelabs.conductor.ControllerChangeHandler; import com.bluelinelabs.conductor.ControllerChangeType; import com.bluelinelabs.conductor.RouterTransaction; diff --git a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/RxLifecycle2Controller.java b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/RxLifecycle2Controller.java index cefc07b..89c4511 100644 --- a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/RxLifecycle2Controller.java +++ b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/RxLifecycle2Controller.java @@ -1,13 +1,14 @@ package com.bluelinelabs.conductor.demo.controllers; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + import com.bluelinelabs.conductor.ControllerChangeHandler; import com.bluelinelabs.conductor.ControllerChangeType; import com.bluelinelabs.conductor.RouterTransaction; diff --git a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/RxLifecycleController.java b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/RxLifecycleController.java index 72bea75..3fa5fca 100644 --- a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/RxLifecycleController.java +++ b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/RxLifecycleController.java @@ -1,13 +1,14 @@ package com.bluelinelabs.conductor.demo.controllers; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + import com.bluelinelabs.conductor.ControllerChangeHandler; import com.bluelinelabs.conductor.ControllerChangeType; import com.bluelinelabs.conductor.RouterTransaction; diff --git a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/base/RefWatchingController.java b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/base/RefWatchingController.java index 39d0739..1ffb5b0 100644 --- a/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/base/RefWatchingController.java +++ b/demo/src/main/java/com/bluelinelabs/conductor/demo/controllers/base/RefWatchingController.java @@ -1,6 +1,7 @@ package com.bluelinelabs.conductor.demo.controllers.base; import android.os.Bundle; + import androidx.annotation.NonNull; import com.bluelinelabs.conductor.ControllerChangeHandler; diff --git a/dependencies.gradle b/dependencies.gradle index fe2865a..47a4396 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -15,6 +15,9 @@ ext { junitVersion = '4.12' roboelectricVersion = '3.8' lintVersion = '26.1.2' + kotlinVersion = '1.3.71' + + kotlinStd = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion" material = "com.google.android.material:material:1.0.0" androidxAnnotations = "androidx.annotation:annotation:1.1.0"