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.
This commit is contained in:
Paul Woitaschek
2020-03-30 16:37:13 +02:00
committed by GitHub
parent a51f4192cb
commit 589cb91fff
51 changed files with 879 additions and 763 deletions
-1
View File
@@ -5,7 +5,6 @@
.checkstyle
# IntelliJ IDEA
.idea
*.iml
*.ipr
*.iws
+8
View File
@@ -0,0 +1,8 @@
/libraries
/runConfigurations.xml
/misc.xml
/vcs.xml
/workspace.xml
/caches
/gradle.xml
/modules.xml
+129
View File
@@ -0,0 +1,129 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>
+5
View File
@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>
+22
View File
@@ -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')
-3
View File
@@ -1,8 +1,5 @@
apply plugin: 'java'
targetCompatibility = JavaVersion.VERSION_1_7
sourceCompatibility = JavaVersion.VERSION_1_7
configurations {
lintChecks
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
-5
View File
@@ -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
+2 -5
View File
@@ -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')
}
@@ -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<RouterTransaction> {
@NonNull
RouterTransaction pop() {
RouterTransaction popped = backstack.pop();
popped.controller.destroy();
popped.controller().destroy();
return popped;
}
@@ -89,7 +90,7 @@ class Backstack implements Iterable<RouterTransaction> {
boolean contains(@NonNull Controller controller) {
for (RouterTransaction transaction : backstack) {
if (controller == transaction.controller) {
if (controller == transaction.controller()) {
return true;
}
}
@@ -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--;
}
}
@@ -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--
}
}
@@ -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;
}
}
@@ -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() }
}
@@ -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<RouterTransaction>() {
@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) {
}
}
@@ -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<ControllerChangeListener> listeners;
public ChangeTransaction(@Nullable Controller to, @Nullable Controller from, boolean isPush, @Nullable ViewGroup container, @Nullable ControllerChangeHandler changeHandler, @NonNull List<ControllerChangeListener> 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<ControllerChangeListener> listeners;
public ChangeTransaction(@Nullable Controller to, @Nullable Controller from, boolean isPush, @Nullable ViewGroup container, @Nullable ControllerChangeHandler changeHandler, @NonNull List<ControllerChangeListener> listeners) {
this.to = to;
this.from = from;
this.isPush = isPush;
this.container = container;
this.changeHandler = changeHandler;
this.listeners = listeners;
}
}
/**
@@ -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;
}
}
@@ -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);
}
@@ -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<RouterTransaction> newBackstack, @Nullable ControllerChangeHandler changeHandler) {
if (isDetachFrozen) {
for (RouterTransaction transaction : newBackstack) {
transaction.controller.setDetachFrozen(true);
transaction.controller().setDetachFrozen(true);
}
}
super.setBackstack(newBackstack, changeHandler);
@@ -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<RouterTransaction> 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<RouterTransaction> 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<View> 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<Integer> 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<RouterTransaction> 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.");
}
}
@@ -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;
}
}
@@ -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)
}
@@ -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<View> 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<View> toSharedElements, @NonNull final List<View> enteringViews, @Nullable final List<View> exitingViews) {
OneShotPreDrawListener.add(true, container, new Runnable() {
@Override
public void run() {
if (enterTransition != null) {
enterTransition.removeTarget(nonExistentView);
List<View> views = configureEnteringExitingViews(enterTransition, to, toSharedElements, nonExistentView);
enteringViews.addAll(views);
}
OneShotPreDrawListener.add(true, container, () -> {
if (enterTransition != null) {
enterTransition.removeTarget(nonExistentView);
List<View> views = configureEnteringExitingViews(enterTransition, to, toSharedElements, nonExistentView);
enteringViews.addAll(views);
}
if (exitingViews != null) {
if (exitTransition != null) {
List<View> tempExiting = new ArrayList<>();
tempExiting.add(nonExistentView);
LegacyTransitionUtils.replaceTargets(exitTransition, exitingViews, tempExiting);
}
exitingViews.clear();
exitingViews.add(nonExistentView);
if (exitingViews != null) {
if (exitTransition != null) {
List<View> 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<String, View> capturedToSharedElements = captureToSharedElements(to, isPush);
OneShotPreDrawListener.add(true, container, () -> {
ArrayMap<String, View> 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<View> 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<View> 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);
}
});
}
@@ -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);
}
});
}
@@ -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<Router> getRouters() {
return new ArrayList<Router>(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<String>();
permissionRequestMap = permissionParcel != null ? permissionParcel.getStringSparseArray() : new SparseArray<>();
StringSparseArrayParceler activityParcel = savedInstanceState.getParcelable(KEY_ACTIVITY_REQUEST_CODES);
activityRequestMap = activityParcel != null ? activityParcel.getStringSparseArray() : new SparseArray<String>();
activityRequestMap = activityParcel != null ? activityParcel.getStringSparseArray() : new SparseArray<>();
ArrayList<PendingPermissionRequest> pendingRequests = savedInstanceState.getParcelableArrayList(KEY_PENDING_PERMISSION_REQUESTS);
pendingPermissionRequests = pendingRequests != null ? pendingRequests : new ArrayList<PendingPermissionRequest>();
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);
@@ -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;
}
}
@@ -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
}
@@ -1,5 +0,0 @@
package com.bluelinelabs.conductor.internal;
public interface RouterRequiringFunc {
void execute();
}
@@ -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()
}
@@ -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);
}
}
}
@@ -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)
@@ -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);
}
}
@@ -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"
@@ -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();
}
});
}
@@ -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<Boolean> changeEndReferences = new ArrayList<>();
final List<Boolean> postCreateViewReferences = new ArrayList<>();
final List<Boolean> postAttachReferences = new ArrayList<>();
@@ -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());
@@ -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());
@@ -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<RouterTransaction> 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<RouterTransaction> 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<RouterTransaction> 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();
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -1,6 +1,7 @@
package com.bluelinelabs.conductor.demo.controllers.base;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.bluelinelabs.conductor.ControllerChangeHandler;
+3
View File
@@ -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"