diff --git a/build.gradle b/build.gradle index 9b0927d..5b94bb3 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0-alpha01' + classpath 'com.android.tools.build:gradle:3.5.0' // For the library uploading to the Bintray classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.1' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 367bbb2..3ebf4c7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1-milestone-1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/library/build.gradle b/library/build.gradle index 415d153..fb0f944 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -8,6 +8,7 @@ targetCompatibility = JavaVersion.VERSION_1_7 dependencies { compileOnly project(':stub-android') compileOnly 'com.google.android:android:4.1.1.4' + implementation "org.jetbrains:annotations:16.0.3" } ext { @@ -16,7 +17,7 @@ ext { bintrayName = 'cicerone' publishedGroupId = 'ru.terrakok.cicerone' artifact = 'cicerone' - libraryVersion = '5.0.0' + libraryVersion = '5.1.0' gitUrl = 'https://github.com/terrakok/Cicerone' allLicenses = ['MIT'] } @@ -24,7 +25,7 @@ ext { // Configuration of the library uploading to the Bintray // Note: Call 'bintrayUpload' task (it will execute 'install' task first) // I try to include as little properties as possible in these files -project.archivesBaseName ='cicerone' // to fix that project name different from artifact name +project.archivesBaseName = 'cicerone' // to fix that project name different from artifact name apply from: 'androidmaven.gradle' apply from: 'bintray.gradle' diff --git a/library/src/main/java/ru/terrakok/cicerone/BaseRouter.java b/library/src/main/java/ru/terrakok/cicerone/BaseRouter.java index f34c394..45cad1a 100644 --- a/library/src/main/java/ru/terrakok/cicerone/BaseRouter.java +++ b/library/src/main/java/ru/terrakok/cicerone/BaseRouter.java @@ -4,6 +4,8 @@ package ru.terrakok.cicerone; +import org.jetbrains.annotations.NotNull; + import ru.terrakok.cicerone.commands.Command; /** @@ -17,6 +19,7 @@ public BaseRouter() { this.commandBuffer = new CommandBuffer(); } + @NotNull CommandBuffer getCommandBuffer() { return commandBuffer; } @@ -26,7 +29,7 @@ CommandBuffer getCommandBuffer() { * * @param commands navigation command array to execute */ - protected void executeCommands(Command... commands) { + protected void executeCommands(@NotNull Command... commands) { commandBuffer.executeCommands(commands); } } diff --git a/library/src/main/java/ru/terrakok/cicerone/Cicerone.java b/library/src/main/java/ru/terrakok/cicerone/Cicerone.java index 09ef339..c2cf8e3 100644 --- a/library/src/main/java/ru/terrakok/cicerone/Cicerone.java +++ b/library/src/main/java/ru/terrakok/cicerone/Cicerone.java @@ -4,6 +4,8 @@ package ru.terrakok.cicerone; +import org.jetbrains.annotations.NotNull; + /** * Cicerone is the holder for other library components. * To use it, instantiate it using one of the {@link #create()} methods. @@ -15,14 +17,16 @@ public class Cicerone { private T router; - private Cicerone(T router) { + private Cicerone(@NotNull T router) { this.router = router; } + @NotNull public NavigatorHolder getNavigatorHolder() { return router.getCommandBuffer(); } + @NotNull public T getRouter() { return router; } @@ -30,6 +34,7 @@ public T getRouter() { /** * Creates the Cicerone instance with the default {@link Router router} */ + @NotNull public static Cicerone create() { return create(new Router()); } @@ -38,7 +43,8 @@ public static Cicerone create() { * Creates the Cicerone instance with the custom router. * @param customRouter the custom router extending {@link BaseRouter} */ - public static Cicerone create(T customRouter) { + @NotNull + public static Cicerone create(@NotNull T customRouter) { return new Cicerone<>(customRouter); } } diff --git a/library/src/main/java/ru/terrakok/cicerone/CommandBuffer.java b/library/src/main/java/ru/terrakok/cicerone/CommandBuffer.java index 4e0645b..7d1ae67 100644 --- a/library/src/main/java/ru/terrakok/cicerone/CommandBuffer.java +++ b/library/src/main/java/ru/terrakok/cicerone/CommandBuffer.java @@ -4,6 +4,9 @@ package ru.terrakok.cicerone; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.LinkedList; import java.util.Queue; @@ -18,7 +21,7 @@ class CommandBuffer implements NavigatorHolder { private Queue pendingCommands = new LinkedList<>(); @Override - public void setNavigator(Navigator navigator) { + public void setNavigator(@Nullable Navigator navigator) { this.navigator = navigator; while (!pendingCommands.isEmpty()) { if (navigator != null) { @@ -37,7 +40,7 @@ public void removeNavigator() { * Else puts it to the pending commands queue to pass it later. * @param commands navigation command array */ - void executeCommands(Command[] commands) { + void executeCommands(@NotNull Command[] commands) { if (navigator != null) { navigator.applyCommands(commands); } else { diff --git a/library/src/main/java/ru/terrakok/cicerone/Navigator.java b/library/src/main/java/ru/terrakok/cicerone/Navigator.java index de44ada..36d6975 100644 --- a/library/src/main/java/ru/terrakok/cicerone/Navigator.java +++ b/library/src/main/java/ru/terrakok/cicerone/Navigator.java @@ -4,6 +4,8 @@ package ru.terrakok.cicerone; +import org.jetbrains.annotations.NotNull; + import ru.terrakok.cicerone.commands.Command; /** @@ -17,5 +19,5 @@ public interface Navigator { * * @param commands the navigation command array to apply per single transaction */ - void applyCommands(Command[] commands); + void applyCommands(@NotNull Command[] commands); } diff --git a/library/src/main/java/ru/terrakok/cicerone/NavigatorHolder.java b/library/src/main/java/ru/terrakok/cicerone/NavigatorHolder.java index 79b2c8c..a61e4aa 100644 --- a/library/src/main/java/ru/terrakok/cicerone/NavigatorHolder.java +++ b/library/src/main/java/ru/terrakok/cicerone/NavigatorHolder.java @@ -4,6 +4,8 @@ package ru.terrakok.cicerone; +import org.jetbrains.annotations.NotNull; + /** * Navigator holder interface. * Use it to connect a {@link Navigator} to the {@link Cicerone}. @@ -15,7 +17,7 @@ public interface NavigatorHolder { * * @param navigator new active Navigator */ - void setNavigator(Navigator navigator); + void setNavigator(@NotNull Navigator navigator); /** * Remove the current Navigator and stop receive commands. diff --git a/library/src/main/java/ru/terrakok/cicerone/Router.java b/library/src/main/java/ru/terrakok/cicerone/Router.java index 1e04b99..3243e9c 100644 --- a/library/src/main/java/ru/terrakok/cicerone/Router.java +++ b/library/src/main/java/ru/terrakok/cicerone/Router.java @@ -4,6 +4,9 @@ package ru.terrakok.cicerone; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import ru.terrakok.cicerone.commands.Back; import ru.terrakok.cicerone.commands.BackTo; import ru.terrakok.cicerone.commands.Command; @@ -27,7 +30,7 @@ public Router() { * * @param screen screen */ - public void navigateTo(Screen screen) { + public void navigateTo(@NotNull Screen screen) { executeCommands(new Forward(screen)); } @@ -36,7 +39,7 @@ public void navigateTo(Screen screen) { * * @param screen screen */ - public void newRootScreen(Screen screen) { + public void newRootScreen(@NotNull Screen screen) { executeCommands( new BackTo(null), new Replace(screen) @@ -51,7 +54,7 @@ public void newRootScreen(Screen screen) { * * @param screen screen */ - public void replaceScreen(Screen screen) { + public void replaceScreen(@NotNull Screen screen) { executeCommands(new Replace(screen)); } @@ -62,7 +65,7 @@ public void replaceScreen(Screen screen) { * * @param screen screen */ - public void backTo(Screen screen) { + public void backTo(@Nullable Screen screen) { executeCommands(new BackTo(screen)); } @@ -70,7 +73,7 @@ public void backTo(Screen screen) { * Opens several screens inside single transaction. * @param screens */ - public void newChain(Screen... screens) { + public void newChain(@NotNull Screen... screens) { Command[] commands = new Command[screens.length]; for (int i = 0; i < commands.length; i++) { commands[i] = new Forward(screens[i]); @@ -82,7 +85,7 @@ public void newChain(Screen... screens) { * Clear current stack and open several screens inside single transaction. * @param screens */ - public void newRootChain(Screen... screens) { + public void newRootChain(@NotNull Screen... screens) { Command[] commands = new Command[screens.length + 1]; commands[0] = new BackTo(null); if (screens.length > 0) { diff --git a/library/src/main/java/ru/terrakok/cicerone/Screen.java b/library/src/main/java/ru/terrakok/cicerone/Screen.java index b229111..0c1652d 100644 --- a/library/src/main/java/ru/terrakok/cicerone/Screen.java +++ b/library/src/main/java/ru/terrakok/cicerone/Screen.java @@ -1,11 +1,14 @@ package ru.terrakok.cicerone; +import org.jetbrains.annotations.NotNull; + /** * Screen is class for description application screen. */ public abstract class Screen { protected String screenKey = getClass().getCanonicalName(); + @NotNull public String getScreenKey() { return screenKey; } diff --git a/library/src/main/java/ru/terrakok/cicerone/android/pure/AppNavigator.java b/library/src/main/java/ru/terrakok/cicerone/android/pure/AppNavigator.java index 1792405..f8256ab 100644 --- a/library/src/main/java/ru/terrakok/cicerone/android/pure/AppNavigator.java +++ b/library/src/main/java/ru/terrakok/cicerone/android/pure/AppNavigator.java @@ -6,16 +6,13 @@ import android.app.FragmentTransaction; import android.content.Intent; import android.os.Bundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import ru.terrakok.cicerone.Navigator; +import ru.terrakok.cicerone.commands.*; import java.util.LinkedList; -import ru.terrakok.cicerone.Navigator; -import ru.terrakok.cicerone.commands.Back; -import ru.terrakok.cicerone.commands.BackTo; -import ru.terrakok.cicerone.commands.Command; -import ru.terrakok.cicerone.commands.Forward; -import ru.terrakok.cicerone.commands.Replace; - /** * Navigator implementation for launch fragments and activities.
* Feature {@link BackTo} works only for fragments.
@@ -23,30 +20,34 @@ */ public class AppNavigator implements Navigator { - private final Activity activity; - private final FragmentManager fragmentManager; - private final int containerId; - private LinkedList localStackCopy; + protected final Activity activity; + protected final FragmentManager fragmentManager; + protected final int containerId; + protected LinkedList localStackCopy; - public AppNavigator(Activity activity, int containerId) { + public AppNavigator(@NotNull Activity activity, int containerId) { this(activity, activity.getFragmentManager(), containerId); } - public AppNavigator(Activity activity, FragmentManager fragmentManager, int containerId) { + public AppNavigator(@NotNull Activity activity, @NotNull FragmentManager fragmentManager, int containerId) { this.activity = activity; this.fragmentManager = fragmentManager; this.containerId = containerId; } @Override - public void applyCommands(Command[] commands) { + public void applyCommands(@NotNull Command[] commands) { fragmentManager.executePendingTransactions(); //copy stack before apply commands copyStackToLocal(); for (Command command : commands) { - applyCommand(command); + try { + applyCommand(command); + } catch (RuntimeException e) { + errorOnApplyCommand(command, e); + } } } @@ -64,7 +65,7 @@ private void copyStackToLocal() { * * @param command the navigation command to apply */ - protected void applyCommand(Command command) { + protected void applyCommand(@NotNull Command command) { if (command instanceof Forward) { activityForward((Forward) command); } else if (command instanceof Replace) { @@ -77,7 +78,7 @@ protected void applyCommand(Command command) { } - protected void activityForward(Forward command) { + protected void activityForward(@NotNull Forward command) { AppScreen screen = (AppScreen) command.getScreen(); Intent activityIntent = screen.getActivityIntent(activity); @@ -90,7 +91,7 @@ protected void activityForward(Forward command) { } } - protected void fragmentForward(Forward command) { + protected void fragmentForward(@NotNull Forward command) { AppScreen screen = (AppScreen) command.getScreen(); Fragment fragment = createFragment(screen); @@ -123,7 +124,7 @@ protected void activityBack() { activity.finish(); } - protected void activityReplace(Replace command) { + protected void activityReplace(@NotNull Replace command) { AppScreen screen = (AppScreen) command.getScreen(); Intent activityIntent = screen.getActivityIntent(activity); @@ -137,7 +138,7 @@ protected void activityReplace(Replace command) { } } - protected void fragmentReplace(Replace command) { + protected void fragmentReplace(@NotNull Replace command) { AppScreen screen = (AppScreen) command.getScreen(); Fragment fragment = createFragment(screen); @@ -179,7 +180,7 @@ protected void fragmentReplace(Replace command) { /** * Performs {@link BackTo} command transition */ - protected void backTo(BackTo command) { + protected void backTo(@NotNull BackTo command) { if (command.getScreen() == null) { backToRoot(); } else { @@ -213,10 +214,10 @@ private void backToRoot() { * @param nextFragment next screen fragment * @param fragmentTransaction fragment transaction */ - protected void setupFragmentTransaction(Command command, - Fragment currentFragment, - Fragment nextFragment, - FragmentTransaction fragmentTransaction) { + protected void setupFragmentTransaction(@NotNull Command command, + @Nullable Fragment currentFragment, + @Nullable Fragment nextFragment, + @NotNull FragmentTransaction fragmentTransaction) { } /** @@ -226,11 +227,14 @@ protected void setupFragmentTransaction(Command command, * @param activityIntent activity intent * @return transition options */ - protected Bundle createStartActivityOptions(Command command, Intent activityIntent) { + @Nullable + protected Bundle createStartActivityOptions(@NotNull Command command, @NotNull Intent activityIntent) { return null; } - private void checkAndStartActivity(AppScreen screen, Intent activityIntent, Bundle options) { + private void checkAndStartActivity(@NotNull AppScreen screen, + @NotNull Intent activityIntent, + @Nullable Bundle options) { // Check if we can start activity if (activityIntent.resolveActivity(activity.getPackageManager()) != null) { activity.startActivity(activityIntent, options); @@ -245,7 +249,7 @@ private void checkAndStartActivity(AppScreen screen, Intent activityIntent, Bund * @param screen screen * @param activityIntent intent passed to start Activity for the {@code screenKey} */ - protected void unexistingActivity(AppScreen screen, Intent activityIntent) { + protected void unexistingActivity(@NotNull AppScreen screen, @NotNull Intent activityIntent) { // Do nothing by default } @@ -255,11 +259,13 @@ protected void unexistingActivity(AppScreen screen, Intent activityIntent) { * @param screen screen * @return instantiated fragment for the passed screen */ - protected Fragment createFragment(AppScreen screen) { + @Nullable + protected Fragment createFragment(@NotNull AppScreen screen) { Fragment fragment = screen.getFragment(); if (fragment == null) { errorWhileCreatingScreen(screen); + throw new RuntimeException("Can't create a screen: " + screen.getScreenKey()); } return fragment; } @@ -270,11 +276,29 @@ protected Fragment createFragment(AppScreen screen) { * * @param screen screen */ - protected void backToUnexisting(AppScreen screen) { + protected void backToUnexisting(@NotNull AppScreen screen) { backToRoot(); } - protected void errorWhileCreatingScreen(AppScreen screen) { - throw new RuntimeException("Can't create a screen: " + screen.getScreenKey()); + /** + * Called when we tried to create new intent or fragment but didn't receive them. + * + * @param screen screen + */ + protected void errorWhileCreatingScreen(@NotNull AppScreen screen) { + // Do nothing by default + } + + /** + * Override this method if you want to handle apply command error. + * + * @param command command + * @param error error + */ + protected void errorOnApplyCommand( + @NotNull Command command, + @NotNull RuntimeException error + ) { + throw error; } } diff --git a/library/src/main/java/ru/terrakok/cicerone/android/pure/AppScreen.java b/library/src/main/java/ru/terrakok/cicerone/android/pure/AppScreen.java index d9e9a03..8e409b7 100644 --- a/library/src/main/java/ru/terrakok/cicerone/android/pure/AppScreen.java +++ b/library/src/main/java/ru/terrakok/cicerone/android/pure/AppScreen.java @@ -4,6 +4,8 @@ import android.content.Context; import android.content.Intent; +import org.jetbrains.annotations.Nullable; + import ru.terrakok.cicerone.Screen; /** @@ -13,10 +15,12 @@ */ public abstract class AppScreen extends Screen { + @Nullable public Fragment getFragment() { return null; } + @Nullable public Intent getActivityIntent(Context context) { return null; } diff --git a/library/src/main/java/ru/terrakok/cicerone/android/support/FragmentParams.java b/library/src/main/java/ru/terrakok/cicerone/android/support/FragmentParams.java new file mode 100644 index 0000000..e3cf57c --- /dev/null +++ b/library/src/main/java/ru/terrakok/cicerone/android/support/FragmentParams.java @@ -0,0 +1,36 @@ +package ru.terrakok.cicerone.android.support; + +import android.os.Bundle; + +import androidx.fragment.app.Fragment; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class FragmentParams { + + @NotNull + private final Class fragmentClass; + @Nullable + private final Bundle arguments; + + @NotNull + public final Class getFragmentClass() { + return this.fragmentClass; + } + + @Nullable + public final Bundle getArguments() { + return this.arguments; + } + + public FragmentParams(@NotNull Class fragmentClass, @Nullable Bundle arguments) { + this.fragmentClass = fragmentClass; + this.arguments = arguments; + } + + public FragmentParams(@NotNull Class fragmentClass) { + this.fragmentClass = fragmentClass; + this.arguments = null; + } +} diff --git a/library/src/main/java/ru/terrakok/cicerone/android/support/SupportAppNavigator.java b/library/src/main/java/ru/terrakok/cicerone/android/support/SupportAppNavigator.java index b5a884a..6f8672d 100644 --- a/library/src/main/java/ru/terrakok/cicerone/android/support/SupportAppNavigator.java +++ b/library/src/main/java/ru/terrakok/cicerone/android/support/SupportAppNavigator.java @@ -7,16 +7,13 @@ import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import ru.terrakok.cicerone.Navigator; +import ru.terrakok.cicerone.commands.*; import java.util.LinkedList; -import ru.terrakok.cicerone.Navigator; -import ru.terrakok.cicerone.commands.Back; -import ru.terrakok.cicerone.commands.BackTo; -import ru.terrakok.cicerone.commands.Command; -import ru.terrakok.cicerone.commands.Forward; -import ru.terrakok.cicerone.commands.Replace; - /** * Navigator implementation for launch fragments and activities.
* Feature {@link BackTo} works only for fragments.
@@ -24,30 +21,34 @@ */ public class SupportAppNavigator implements Navigator { - private final Activity activity; - private final FragmentManager fragmentManager; - private final int containerId; - private LinkedList localStackCopy; + protected final Activity activity; + protected final FragmentManager fragmentManager; + protected final int containerId; + protected LinkedList localStackCopy; - public SupportAppNavigator(FragmentActivity activity, int containerId) { + public SupportAppNavigator(@NotNull FragmentActivity activity, int containerId) { this(activity, activity.getSupportFragmentManager(), containerId); } - public SupportAppNavigator(FragmentActivity activity, FragmentManager fragmentManager, int containerId) { + public SupportAppNavigator(@NotNull FragmentActivity activity, @NotNull FragmentManager fragmentManager, int containerId) { this.activity = activity; this.fragmentManager = fragmentManager; this.containerId = containerId; } @Override - public void applyCommands(Command[] commands) { + public void applyCommands(@NotNull Command[] commands) { fragmentManager.executePendingTransactions(); //copy stack before apply commands copyStackToLocal(); for (Command command : commands) { - applyCommand(command); + try { + applyCommand(command); + } catch (RuntimeException e) { + errorOnApplyCommand(command, e); + } } } @@ -65,7 +66,7 @@ private void copyStackToLocal() { * * @param command the navigation command to apply */ - protected void applyCommand(Command command) { + protected void applyCommand(@NotNull Command command) { if (command instanceof Forward) { activityForward((Forward) command); } else if (command instanceof Replace) { @@ -78,7 +79,7 @@ protected void applyCommand(Command command) { } - protected void activityForward(Forward command) { + protected void activityForward(@NotNull Forward command) { SupportAppScreen screen = (SupportAppScreen) command.getScreen(); Intent activityIntent = screen.getActivityIntent(activity); @@ -91,9 +92,11 @@ protected void activityForward(Forward command) { } } - protected void fragmentForward(Forward command) { + protected void fragmentForward(@NotNull Forward command) { SupportAppScreen screen = (SupportAppScreen) command.getScreen(); - Fragment fragment = createFragment(screen); + + FragmentParams fragmentParams = screen.getFragmentParams(); + Fragment fragment = fragmentParams == null ? createFragment(screen) : null; FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); @@ -101,11 +104,15 @@ protected void fragmentForward(Forward command) { command, fragmentManager.findFragmentById(containerId), fragment, - fragmentTransaction - ); + fragmentTransaction); + + if (fragmentParams != null) { + fragmentTransaction.replace(containerId, fragmentParams.getFragmentClass(), fragmentParams.getArguments()); + } else { + fragmentTransaction.replace(containerId, fragment); + } fragmentTransaction - .replace(containerId, fragment) .addToBackStack(screen.getScreenKey()) .commit(); localStackCopy.add(screen.getScreenKey()); @@ -124,7 +131,7 @@ protected void activityBack() { activity.finish(); } - protected void activityReplace(Replace command) { + protected void activityReplace(@NotNull Replace command) { SupportAppScreen screen = (SupportAppScreen) command.getScreen(); Intent activityIntent = screen.getActivityIntent(activity); @@ -138,9 +145,11 @@ protected void activityReplace(Replace command) { } } - protected void fragmentReplace(Replace command) { + protected void fragmentReplace(@NotNull Replace command) { SupportAppScreen screen = (SupportAppScreen) command.getScreen(); - Fragment fragment = createFragment(screen); + + FragmentParams fragmentParams = screen.getFragmentParams(); + Fragment fragment = fragmentParams == null ? createFragment(screen) : null; if (localStackCopy.size() > 0) { fragmentManager.popBackStack(); @@ -155,8 +164,15 @@ protected void fragmentReplace(Replace command) { fragmentTransaction ); + if (fragmentParams != null) { + fragmentTransaction.replace( + containerId, + fragmentParams.getFragmentClass(), + fragmentParams.getArguments()); + } else { + fragmentTransaction.replace(containerId, fragment); + } fragmentTransaction - .replace(containerId, fragment) .addToBackStack(screen.getScreenKey()) .commit(); localStackCopy.add(screen.getScreenKey()); @@ -180,7 +196,7 @@ protected void fragmentReplace(Replace command) { /** * Performs {@link BackTo} command transition */ - protected void backTo(BackTo command) { + protected void backTo(@NotNull BackTo command) { if (command.getScreen() == null) { backToRoot(); } else { @@ -214,10 +230,10 @@ private void backToRoot() { * @param nextFragment next screen fragment * @param fragmentTransaction fragment transaction */ - protected void setupFragmentTransaction(Command command, - Fragment currentFragment, - Fragment nextFragment, - FragmentTransaction fragmentTransaction) { + protected void setupFragmentTransaction(@NotNull Command command, + @Nullable Fragment currentFragment, + @Nullable Fragment nextFragment, + @NotNull FragmentTransaction fragmentTransaction) { } /** @@ -227,11 +243,12 @@ protected void setupFragmentTransaction(Command command, * @param activityIntent activity intent * @return transition options */ - protected Bundle createStartActivityOptions(Command command, Intent activityIntent) { + @Nullable + protected Bundle createStartActivityOptions(@NotNull Command command, @NotNull Intent activityIntent) { return null; } - private void checkAndStartActivity(SupportAppScreen screen, Intent activityIntent, Bundle options) { + private void checkAndStartActivity(@NotNull SupportAppScreen screen, @NotNull Intent activityIntent, @Nullable Bundle options) { // Check if we can start activity if (activityIntent.resolveActivity(activity.getPackageManager()) != null) { activity.startActivity(activityIntent, options); @@ -246,7 +263,7 @@ private void checkAndStartActivity(SupportAppScreen screen, Intent activityInten * @param screen screen * @param activityIntent intent passed to start Activity for the {@code screenKey} */ - protected void unexistingActivity(SupportAppScreen screen, Intent activityIntent) { + protected void unexistingActivity(@NotNull SupportAppScreen screen, @NotNull Intent activityIntent) { // Do nothing by default } @@ -256,11 +273,13 @@ protected void unexistingActivity(SupportAppScreen screen, Intent activityIntent * @param screen screen * @return instantiated fragment for the passed screen */ - protected Fragment createFragment(SupportAppScreen screen) { + @Nullable + protected Fragment createFragment(@NotNull SupportAppScreen screen) { Fragment fragment = screen.getFragment(); if (fragment == null) { errorWhileCreatingScreen(screen); + throw new RuntimeException("Can't create a screen: " + screen.getScreenKey()); } return fragment; } @@ -271,11 +290,29 @@ protected Fragment createFragment(SupportAppScreen screen) { * * @param screen screen */ - protected void backToUnexisting(SupportAppScreen screen) { + protected void backToUnexisting(@NotNull SupportAppScreen screen) { backToRoot(); } - protected void errorWhileCreatingScreen(SupportAppScreen screen) { - throw new RuntimeException("Can't create a screen: " + screen.getScreenKey()); + /** + * Called when we tried to create new intent or fragment but didn't receive them. + * + * @param screen screen + */ + protected void errorWhileCreatingScreen(@NotNull SupportAppScreen screen) { + // Do nothing by default + } + + /** + * Override this method if you want to handle apply command error. + * + * @param command command + * @param error error + */ + protected void errorOnApplyCommand( + @NotNull Command command, + @NotNull RuntimeException error + ) { + throw error; } } diff --git a/library/src/main/java/ru/terrakok/cicerone/android/support/SupportAppScreen.java b/library/src/main/java/ru/terrakok/cicerone/android/support/SupportAppScreen.java index 554d17f..067ec40 100644 --- a/library/src/main/java/ru/terrakok/cicerone/android/support/SupportAppScreen.java +++ b/library/src/main/java/ru/terrakok/cicerone/android/support/SupportAppScreen.java @@ -2,8 +2,11 @@ import android.content.Context; import android.content.Intent; -import androidx.fragment.app.Fragment; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import androidx.fragment.app.Fragment; import ru.terrakok.cicerone.Screen; /** @@ -13,11 +16,18 @@ */ public abstract class SupportAppScreen extends Screen { + @Nullable public Fragment getFragment() { return null; } - public Intent getActivityIntent(Context context) { + @Nullable + public Intent getActivityIntent(@NotNull Context context) { + return null; + } + + @Nullable + public FragmentParams getFragmentParams() { return null; } } diff --git a/library/src/main/java/ru/terrakok/cicerone/commands/BackTo.java b/library/src/main/java/ru/terrakok/cicerone/commands/BackTo.java index 7df8570..2cf11a0 100644 --- a/library/src/main/java/ru/terrakok/cicerone/commands/BackTo.java +++ b/library/src/main/java/ru/terrakok/cicerone/commands/BackTo.java @@ -4,6 +4,8 @@ package ru.terrakok.cicerone.commands; +import org.jetbrains.annotations.Nullable; + import ru.terrakok.cicerone.Navigator; import ru.terrakok.cicerone.Screen; @@ -20,10 +22,11 @@ public class BackTo implements Command { * * @param screen screen */ - public BackTo(Screen screen) { + public BackTo(@Nullable Screen screen) { this.screen = screen; } + @Nullable public Screen getScreen() { return screen; } diff --git a/library/src/main/java/ru/terrakok/cicerone/commands/Forward.java b/library/src/main/java/ru/terrakok/cicerone/commands/Forward.java index 2dc5221..46a91e2 100644 --- a/library/src/main/java/ru/terrakok/cicerone/commands/Forward.java +++ b/library/src/main/java/ru/terrakok/cicerone/commands/Forward.java @@ -4,6 +4,8 @@ package ru.terrakok.cicerone.commands; +import org.jetbrains.annotations.NotNull; + import ru.terrakok.cicerone.Screen; /** @@ -17,10 +19,11 @@ public class Forward implements Command { * * @param screen screen */ - public Forward(Screen screen) { + public Forward(@NotNull Screen screen) { this.screen = screen; } + @NotNull public Screen getScreen() { return screen; } diff --git a/library/src/main/java/ru/terrakok/cicerone/commands/Replace.java b/library/src/main/java/ru/terrakok/cicerone/commands/Replace.java index a7d2e19..d34489a 100644 --- a/library/src/main/java/ru/terrakok/cicerone/commands/Replace.java +++ b/library/src/main/java/ru/terrakok/cicerone/commands/Replace.java @@ -4,12 +4,15 @@ package ru.terrakok.cicerone.commands; +import org.jetbrains.annotations.NotNull; + import ru.terrakok.cicerone.Screen; /** * Replaces the current screen. */ public class Replace implements Command { + @NotNull private Screen screen; /** @@ -17,10 +20,11 @@ public class Replace implements Command { * * @param screen screen */ - public Replace(Screen screen) { + public Replace(@NotNull Screen screen) { this.screen = screen; } + @NotNull public Screen getScreen() { return screen; } diff --git a/library/stub-android/src/main/java/androidx/fragment/app/FragmentTransaction.java b/library/stub-android/src/main/java/androidx/fragment/app/FragmentTransaction.java index ce708dc..a4a8731 100644 --- a/library/stub-android/src/main/java/androidx/fragment/app/FragmentTransaction.java +++ b/library/stub-android/src/main/java/androidx/fragment/app/FragmentTransaction.java @@ -1,5 +1,7 @@ package androidx.fragment.app; +import android.os.Bundle; + /** * Created by Konstantin Tckhovrebov (aka @terrakok) * on 11.10.16 @@ -10,6 +12,13 @@ public FragmentTransaction replace(int containerViewId, Fragment fragment) { throw new RuntimeException("Stub!"); } + public final FragmentTransaction replace( + int containerViewId, + Class fragmentClass, + Bundle args) { + throw new RuntimeException("Stub!"); + } + public FragmentTransaction addToBackStack(String name) { throw new RuntimeException("Stub!"); }