Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8cba63328f | |||
| 531cc3ff58 | |||
| c7de32584b | |||
| 625d1f15b6 | |||
| 251fc42f67 | |||
| 0bf8e47c48 | |||
| 7784f74102 | |||
| bfacab984b | |||
| f8a05731d9 | |||
| 116b5066c9 | |||
| 011adca579 | |||
| 95de69a006 | |||
| 6cea976d10 | |||
| c573a8961c | |||
| 6c444fecfb | |||
| 29d1fd1c7d | |||
| f6493507f4 | |||
| b012df262d |
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo.
|
||||
#
|
||||
# Adapted from https://coderwall.com/p/9b_lfq and
|
||||
# http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/
|
||||
|
||||
SLUG="bluelinelabs/Conductor"
|
||||
JDK="oraclejdk8"
|
||||
BRANCH="develop"
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$TRAVIS_REPO_SLUG" != "$SLUG" ]; then
|
||||
echo "Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'."
|
||||
elif [ "$TRAVIS_JDK_VERSION" != "$JDK" ]; then
|
||||
echo "Skipping snapshot deployment: wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'."
|
||||
elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
echo "Skipping snapshot deployment: was pull request."
|
||||
elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then
|
||||
echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'."
|
||||
else
|
||||
echo "Deploying snapshot..."
|
||||
./gradlew clean uploadArchives
|
||||
echo "Snapshot deployed!"
|
||||
fi
|
||||
@@ -15,7 +15,6 @@ gen-external-apklibs
|
||||
# Gradle
|
||||
.gradle
|
||||
build
|
||||
gradle.properties
|
||||
|
||||
# Maven
|
||||
target
|
||||
|
||||
+26
@@ -9,3 +9,29 @@ android:
|
||||
|
||||
script:
|
||||
- ./gradlew test
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
branches:
|
||||
except:
|
||||
- v2
|
||||
- feature/nested_controllers
|
||||
- feature/save_restore_lifecycle
|
||||
|
||||
before_install:
|
||||
- chmod +x .buildscript/deploy_snapshot.sh
|
||||
|
||||
after_success:
|
||||
- .buildscript/deploy_snapshot.sh
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.gradle
|
||||
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: SoRbxmNTxnGY9qPR5Z8HraRLhHrq7eJ2UaHMuiXDSxpLwUI0IMw+8+l59PNdy/C5ZXXrr6jo6cj+sn/4u6VNg74e2h9i//O+kYGvbGJUnBx8uo1INOrVenpzSnIgxbRLxyN3ZDp8YgwJMl8MSCLM1nj2OMzjNRY5EBnEw5h3qNXBs4Hyhpp2FxVk7dA2yLMUZdOpFKJIsqhH1ZHnCEnYrLlx5cVM9yoefFmJ3PptgumtV8ciBnp0lgDGy5nTykPh6zJBz4rAXgOr95WHvoqpyBRAUZIUEgw/vB5aF8/g+CX2gvTlJYF2N9LgJTNHMEwd+zJtmjM8JzkuCfTT3uMDD3JK5O8eNU03a/+9AkbKpK2+Pt829ZPdkObavXi+oJykCmD5IirukVXE9ushR2J+fM4VOvJinsANSI0zjzFpjZMplX63lfhNu/4lj3AWV2G4rkZd3vZQU+4AuhGQ469RA9BFqUJDIsiQQJwHEAWIqo9WNi6H4H8OhferACd2T3d5Y0O3s0EG5JfdADBPh9YDIkB2zEtGc3gGdxFzxVmH48BJViubAHlH4SgJn7gn69T9wyKmJ1M8F9ph/CdhSHT3kADRDELPEEVXCcANG/verCbyxMlAMXvLNKIGgHD+A0/z9QS1WduOOZwWd1mAuNuEg/rq2OB8SoDTv/BseHrXOpc=
|
||||
- secure: WpqrbdAvNUFn5cM/Iu3zJOaDvT3jWGHCRwvxQCzX9F8iJeTggB5dB2rjgUDCx8LJ8UAt0VCeOcGtR1RT3EHyaHorN3NWeLcBFAHSz2sXv+2xGkspsXwjfygghZTCdYEzhhvmWlz9Ln4s4QJ2fBFZA07pG0jw4Cp1hSQiJ1WlKfDQezldj8D3pPwg1oOq4b5+HVucQ6+PPVwzGk2c3etwb5205L8H8flRjZrP95mFa5n/H3b/HFIsKX5p+CPNIKCrjBEmX0nHXiV0+g6lBQBV1iCwT56vfmN8Urm4KLId71iMpmvstDxlBBRQx3sz41vxIWGFn/oN7iXJI6XfzVFkyvrd9XAQLQFffq4KpN0REy1L3rjO46sYRXu1ycCP5VFVAAwKZn+o1q6xRjCuma2Qj4tqY754pwPNyzXnndFLO7hoN8KjOgV2nk75+XlRG8LhP356CHET62QBZgJ+sl+aFM3hhknsaEuDQywo8Uz4WZL0lPmYqm5BImQT9sTEF6uQNofg4gMy/uqgGhpLtseQW3PoJXB6dmD5JdNxlOalkGSQ+aI/q5QvR6ruIiuap66o4Bu+YTvHiS2hVzmldvMmLFsU1/zECSI6Fs/vkwRN55R9mbPROWi8SzvftYk9shkFMC5QC1FXA/CHqX1W5nl/HpMrs8R9uPhdZ1lifCiW8Rk=
|
||||
|
||||
@@ -20,14 +20,21 @@ Conductor is architecture-agnostic and does not try to force any design decision
|
||||
## Installation
|
||||
|
||||
```gradle
|
||||
compile 'com.bluelinelabs:conductor:1.1.4'
|
||||
compile 'com.bluelinelabs:conductor:1.1.5'
|
||||
|
||||
// If you want the components that go along with
|
||||
// Android's support libraries (currently just a PagerAdapter):
|
||||
compile 'com.bluelinelabs:conductor-support:1.1.4'
|
||||
compile 'com.bluelinelabs:conductor-support:1.1.5'
|
||||
|
||||
// If you want RxJava/RxAndroid lifecycle support:
|
||||
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.4'
|
||||
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.5'
|
||||
```
|
||||
|
||||
SNAPSHOT:
|
||||
```gradle
|
||||
compile 'com.bluelinelabs:conductor:1.1.6-SNAPSHOT'
|
||||
compile 'com.bluelinelabs:conductor-support:1.1.6-SNAPSHOT'
|
||||
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.6-SNAPSHOT'
|
||||
```
|
||||
|
||||
## Components to Know
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
apply plugin: 'com.github.dcendents.android-maven'
|
||||
apply plugin: 'com.jfrog.bintray'
|
||||
|
||||
group = 'com.bluelinelabs'
|
||||
version = rootProject.ext.versionName
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
task javadoc(type: Javadoc) {
|
||||
source = android.sourceSets.main.java.srcDirs
|
||||
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
|
||||
exclude '**/R.java'
|
||||
exclude '**/internal/**'
|
||||
failOnError = false
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
classifier = 'javadoc'
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives javadocJar
|
||||
archives sourcesJar
|
||||
}
|
||||
|
||||
if (project.hasProperty('pom_name')) {
|
||||
install {
|
||||
repositories.mavenInstaller {
|
||||
pom.project {
|
||||
name pom_name
|
||||
description pom_description
|
||||
url pom_url
|
||||
packaging pom_packaging
|
||||
groupId 'com.bluelinelabs'
|
||||
artifactId project.hasProperty('artifactId') ? project.ext.artifactId : ''
|
||||
|
||||
organization {
|
||||
name 'BlueLine Labs'
|
||||
url 'http://bluelinelabs.com'
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name 'The Apache Software License, Version 2.0'
|
||||
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url pom_url
|
||||
connection pom_git_connection
|
||||
developerConnection pom_git_connection
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id 'erickuck'
|
||||
name 'Eric Kuck'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bintray {
|
||||
user = project.hasProperty('bintray_username') ? bintray_username : ''
|
||||
key = project.hasProperty('bintray_api_key') ? bintray_api_key : ''
|
||||
configurations = ['archives']
|
||||
|
||||
dryRun = false
|
||||
publish = false
|
||||
|
||||
pkg {
|
||||
repo = 'bluelinelabs'
|
||||
userOrg = 'bluelinelabs'
|
||||
name = pom_name
|
||||
desc = pom_description
|
||||
websiteUrl = pom_url
|
||||
issueTrackerUrl = pom_issue_tracker_url
|
||||
vcsUrl = pom_url
|
||||
licenses = ['Apache-2.0']
|
||||
labels = pom_labels
|
||||
|
||||
version {
|
||||
name = project.version
|
||||
gpg {
|
||||
sign = true
|
||||
passphrase = project.hasProperty('bintray_gpg_passphrase') ? bintray_gpg_passphrase : ''
|
||||
}
|
||||
mavenCentralSync {
|
||||
sync = false
|
||||
user = project.hasProperty('maven_central_username') ? maven_central_username : ''
|
||||
password = project.hasProperty('maven_central_password') ? maven_central_password : ''
|
||||
close = '1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-6
@@ -3,15 +3,10 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.0.0'
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
|
||||
classpath 'com.android.tools.build:gradle:2.1.0'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "com.jfrog.bintray" version "1.5"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
apply from: rootProject.file('dependencies.gradle')
|
||||
apply from: rootProject.file('gradle-mvn-push.gradle')
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
@@ -16,8 +19,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode rootProject.ext.versionCode
|
||||
versionName rootProject.ext.versionName
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,5 +34,3 @@ dependencies {
|
||||
|
||||
ext.artifactId = 'conductor-rxlifecycle'
|
||||
|
||||
apply from: rootProject.file('dependencies.gradle')
|
||||
apply from: rootProject.file('bll-gradle-push.gradle')
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
POM_NAME=Conductor RxLifecycle Extensions
|
||||
POM_ARTIFACT_ID=conductor-rxlifecycle
|
||||
POM_PACKAGING=jar
|
||||
+2
-1
@@ -3,6 +3,7 @@ package com.bluelinelabs.conductor.rxlifecycle;
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.trello.rxlifecycle.LifecycleTransformer;
|
||||
import com.trello.rxlifecycle.OutsideLifecycleException;
|
||||
import com.trello.rxlifecycle.RxLifecycle;
|
||||
|
||||
@@ -20,7 +21,7 @@ public class RxControllerLifecycle {
|
||||
*/
|
||||
@NonNull
|
||||
@CheckResult
|
||||
public static <T> Observable.Transformer<T, T> bindController(@NonNull final Observable<ControllerEvent> lifecycle) {
|
||||
public static <T> LifecycleTransformer<T> bindController(@NonNull final Observable<ControllerEvent> lifecycle) {
|
||||
return RxLifecycle.bind(lifecycle, CONTROLLER_LIFECYCLE);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
apply from: rootProject.file('dependencies.gradle')
|
||||
apply from: rootProject.file('gradle-mvn-push.gradle')
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
@@ -16,8 +19,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode rootProject.ext.versionCode
|
||||
versionName rootProject.ext.versionName
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,5 +31,3 @@ dependencies {
|
||||
|
||||
ext.artifactId = 'conductor-support'
|
||||
|
||||
apply from: rootProject.file('dependencies.gradle')
|
||||
apply from: rootProject.file('bll-gradle-push.gradle')
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
POM_NAME=Conductor Support Extensions
|
||||
POM_ARTIFACT_ID=conductor-support
|
||||
POM_PACKAGING=jar
|
||||
@@ -26,8 +26,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode rootProject.ext.versionCode
|
||||
versionName rootProject.ext.versionName
|
||||
versionCode Integer.parseInt(project.VERSION_CODE)
|
||||
versionName project.VERSION_NAME
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,4 +67,4 @@ project.afterEvaluate {
|
||||
ext.artifactId = 'conductor'
|
||||
|
||||
apply from: rootProject.file('dependencies.gradle')
|
||||
apply from: rootProject.file('bll-gradle-push.gradle')
|
||||
apply from: rootProject.file('gradle-mvn-push.gradle')
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
POM_NAME=Conductor
|
||||
POM_ARTIFACT_ID=conductor
|
||||
POM_PACKAGING=jar
|
||||
@@ -45,7 +45,7 @@ public abstract class Controller {
|
||||
private static final String KEY_TARGET_INSTANCE_ID = "Controller.target.instanceId";
|
||||
private static final String KEY_ARGS = "Controller.args";
|
||||
private static final String KEY_NEEDS_ATTACH = "Controller.needsAttach";
|
||||
private static final String KEY_REQUESTED_PERMISSIONS = "Controller.childControllers";
|
||||
private static final String KEY_REQUESTED_PERMISSIONS = "Controller.requestedPermissions";
|
||||
private static final String KEY_OVERRIDDEN_PUSH_HANDLER = "Controller.overriddenPushHandler";
|
||||
private static final String KEY_OVERRIDDEN_POP_HANDLER = "Controller.overriddenPopHandler";
|
||||
private static final String KEY_VIEW_STATE_HIERARCHY = "Controller.viewState.hierarchy";
|
||||
@@ -71,6 +71,7 @@ public abstract class Controller {
|
||||
private ControllerChangeHandler mOverriddenPushHandler;
|
||||
private ControllerChangeHandler mOverriddenPopHandler;
|
||||
private RetainViewMode mRetainViewMode = RetainViewMode.RELEASE_DETACH;
|
||||
private OnAttachStateChangeListener mOnAttachStateChangeListener;
|
||||
private final List<ChildControllerTransaction> mChildControllers = new ArrayList<>();
|
||||
private final List<LifecycleListener> mLifecycleListeners = new ArrayList<>();
|
||||
private final ArrayList<String> mRequestedPermissions = new ArrayList<>();
|
||||
@@ -256,10 +257,11 @@ public abstract class Controller {
|
||||
|
||||
/**
|
||||
* Returns the child Controller with the given instance id, if available.
|
||||
*
|
||||
* @param instanceId The instance ID being searched for
|
||||
* @return The matching child Controller, if one exists
|
||||
* @deprecated Use {@link #getChildController(String)} or {@link #getChildControllers()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final Controller getChildControllerWithInstanceId(String instanceId) {
|
||||
for (ControllerTransaction transaction : mChildControllers) {
|
||||
if (transaction.controller.getInstanceId().equals(instanceId)) {
|
||||
@@ -269,6 +271,24 @@ public abstract class Controller {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Controller with the given instance id, if available.
|
||||
* May return the controller itself or a matching descendant
|
||||
* @param instanceId The instance ID being searched for
|
||||
* @return The matching Controller, if one exists
|
||||
*/
|
||||
final Controller findController(String instanceId) {
|
||||
if (mInstanceId.equals(instanceId))
|
||||
return this;
|
||||
|
||||
for (ControllerTransaction transaction : mChildControllers) {
|
||||
Controller controllerWithId = transaction.controller.findController(instanceId);
|
||||
if (controllerWithId != null)
|
||||
return controllerWithId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of this Controller's child Controllers
|
||||
*/
|
||||
@@ -792,14 +812,14 @@ public abstract class Controller {
|
||||
container.removeView(child.controller.getView());
|
||||
}
|
||||
}
|
||||
|
||||
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
|
||||
lifecycleListener.postDetach(this, view);
|
||||
}
|
||||
|
||||
if (removeViewRef) {
|
||||
removeViewReference();
|
||||
}
|
||||
|
||||
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
|
||||
lifecycleListener.postDetach(this, view);
|
||||
}
|
||||
} else if (removeViewRef) {
|
||||
removeViewReference();
|
||||
}
|
||||
@@ -817,6 +837,7 @@ public abstract class Controller {
|
||||
|
||||
onDestroyView(mView);
|
||||
|
||||
mView.removeOnAttachStateChangeListener(mOnAttachStateChangeListener);
|
||||
mView = null;
|
||||
|
||||
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
|
||||
@@ -830,6 +851,11 @@ public abstract class Controller {
|
||||
}
|
||||
|
||||
final View inflate(@NonNull ViewGroup parent) {
|
||||
if (mView != null && mView.getParent() != null && mView.getParent() != parent) {
|
||||
detach(mView, true);
|
||||
removeViewReference();
|
||||
}
|
||||
|
||||
if (mView == null) {
|
||||
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
|
||||
lifecycleListener.preCreateView(this);
|
||||
@@ -837,9 +863,13 @@ public abstract class Controller {
|
||||
|
||||
mView = onCreateView(LayoutInflater.from(parent.getContext()), parent);
|
||||
|
||||
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
|
||||
lifecycleListener.postCreateView(this, mView);
|
||||
}
|
||||
|
||||
restoreViewState(mView);
|
||||
|
||||
mView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
|
||||
mOnAttachStateChangeListener = new OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
if (v == mView) {
|
||||
@@ -853,11 +883,8 @@ public abstract class Controller {
|
||||
mViewIsAttached = false;
|
||||
detach(v, true);
|
||||
}
|
||||
});
|
||||
|
||||
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
|
||||
lifecycleListener.postCreateView(this, mView);
|
||||
}
|
||||
};
|
||||
mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
|
||||
}
|
||||
|
||||
return mView;
|
||||
@@ -1032,20 +1059,40 @@ public abstract class Controller {
|
||||
}
|
||||
|
||||
final void createOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
if (mAttached && mHasOptionsMenu && !mOptionsMenuHidden) {
|
||||
onCreateOptionsMenu(menu, inflater);
|
||||
if (mAttached) {
|
||||
if (mHasOptionsMenu && !mOptionsMenuHidden) {
|
||||
onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
for (ChildControllerTransaction child : mChildControllers) {
|
||||
child.controller.createOptionsMenu(menu, inflater);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final void prepareOptionsMenu(Menu menu) {
|
||||
if (mAttached && mHasOptionsMenu && !mOptionsMenuHidden) {
|
||||
onPrepareOptionsMenu(menu);
|
||||
if (mAttached) {
|
||||
if (mHasOptionsMenu && !mOptionsMenuHidden) {
|
||||
onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
for (ChildControllerTransaction child : mChildControllers) {
|
||||
child.controller.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final boolean optionsItemSelected(MenuItem item) {
|
||||
if (mAttached && mHasOptionsMenu && !mOptionsMenuHidden) {
|
||||
return onOptionsItemSelected(item);
|
||||
if (mAttached) {
|
||||
if (mHasOptionsMenu && !mOptionsMenuHidden && onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (ChildControllerTransaction child : mChildControllers) {
|
||||
if (child.controller.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -271,14 +271,10 @@ public class Router {
|
||||
*/
|
||||
public Controller getControllerWithInstanceId(String instanceId) {
|
||||
for (ControllerTransaction transaction : mBackStack) {
|
||||
if (transaction.controller.getInstanceId().equals(instanceId)) {
|
||||
return transaction.controller;
|
||||
} else {
|
||||
Controller childWithId = transaction.controller.getChildControllerWithInstanceId(instanceId);
|
||||
if (childWithId != null) {
|
||||
return childWithId;
|
||||
Controller controllerWithId = transaction.controller.findController(instanceId);
|
||||
if (controllerWithId != null) {
|
||||
return controllerWithId;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,22 @@ public class CallState implements Parcelable {
|
||||
public int restoreInstanceStateCalls;
|
||||
public int saveViewStateCalls;
|
||||
public int restoreViewStateCalls;
|
||||
public int onActivityResultCalls;
|
||||
public int onRequestPermissionsResultCalls;
|
||||
public int createOptionsMenuCalls;
|
||||
|
||||
public CallState() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public CallState(boolean setupForAddedController) {
|
||||
if (setupForAddedController) {
|
||||
changeStartCalls++;
|
||||
changeEndCalls++;
|
||||
createViewCalls++;
|
||||
attachCalls++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
@@ -58,6 +74,15 @@ public class CallState implements Parcelable {
|
||||
if (restoreViewStateCalls != callState.restoreViewStateCalls) {
|
||||
return false;
|
||||
}
|
||||
if (onActivityResultCalls != callState.onActivityResultCalls) {
|
||||
return false;
|
||||
}
|
||||
if (onRequestPermissionsResultCalls != callState.onRequestPermissionsResultCalls) {
|
||||
return false;
|
||||
}
|
||||
if (createOptionsMenuCalls != callState.createOptionsMenuCalls) {
|
||||
return false;
|
||||
}
|
||||
return restoreInstanceStateCalls == callState.restoreInstanceStateCalls;
|
||||
}
|
||||
|
||||
@@ -74,6 +99,9 @@ public class CallState implements Parcelable {
|
||||
result = 31 * result + restoreInstanceStateCalls;
|
||||
result = 31 * result + saveViewStateCalls;
|
||||
result = 31 * result + restoreViewStateCalls;
|
||||
result = 31 * result + onActivityResultCalls;
|
||||
result = 31 * result + onRequestPermissionsResultCalls;
|
||||
result = 31 * result + createOptionsMenuCalls;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -91,6 +119,9 @@ public class CallState implements Parcelable {
|
||||
"\n restoreInstanceStateCalls=" + restoreInstanceStateCalls +
|
||||
"\n saveViewStateCalls=" + saveViewStateCalls +
|
||||
"\n restoreViewStateCalls=" + restoreViewStateCalls +
|
||||
"\n onActivityResultCalls= " + onActivityResultCalls +
|
||||
"\n onRequestPermissionsResultCalls= " + onRequestPermissionsResultCalls +
|
||||
"\n createOptionsMenuCalls= " + createOptionsMenuCalls +
|
||||
"}\n";
|
||||
}
|
||||
|
||||
@@ -110,6 +141,9 @@ public class CallState implements Parcelable {
|
||||
out.writeInt(restoreInstanceStateCalls);
|
||||
out.writeInt(saveViewStateCalls);
|
||||
out.writeInt(restoreViewStateCalls);
|
||||
out.writeInt(onActivityResultCalls);
|
||||
out.writeInt(onRequestPermissionsResultCalls);
|
||||
out.writeInt(createOptionsMenuCalls);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<CallState> CREATOR = new Parcelable.Creator<CallState>() {
|
||||
@@ -127,6 +161,9 @@ public class CallState implements Parcelable {
|
||||
state.restoreInstanceStateCalls = in.readInt();
|
||||
state.saveViewStateCalls = in.readInt();
|
||||
state.restoreViewStateCalls = in.readInt();
|
||||
state.onActivityResultCalls = in.readInt();
|
||||
state.onRequestPermissionsResultCalls = in.readInt();
|
||||
state.createOptionsMenuCalls = in.readInt();
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,627 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller.LifecycleListener;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeCompletedListener;
|
||||
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ActivityController;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(manifest = Config.NONE)
|
||||
public class ControllerLifecycleTests {
|
||||
|
||||
private ActivityController<TestActivity> mActivityController;
|
||||
private Router mRouter;
|
||||
|
||||
private CallState mCurrentCallState;
|
||||
|
||||
public void createActivityController(Bundle savedInstanceState) {
|
||||
mActivityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).start();
|
||||
|
||||
@IdRes int containerId = 4;
|
||||
FrameLayout routerContainer = new FrameLayout(mActivityController.get());
|
||||
routerContainer.setId(containerId);
|
||||
|
||||
mRouter = Conductor.attachRouter(mActivityController.get(), routerContainer, savedInstanceState);
|
||||
if (!mRouter.hasRootController()) {
|
||||
mRouter.setRoot(new TestController());
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
createActivityController(null);
|
||||
|
||||
mCurrentCallState = new CallState();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalLifecycle() {
|
||||
TestController controller = new TestController();
|
||||
attachLifecycleListener(controller);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mRouter.popCurrentController();
|
||||
|
||||
Assert.assertNull(controller.getView());
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycleWithActivityDestroy() {
|
||||
TestController controller = new TestController();
|
||||
attachLifecycleListener(controller);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.stop();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.destroy();
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyViewCalls++;
|
||||
expectedCallState.destroyCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycleWithActivityConfigurationChange() {
|
||||
TestController controller = new TestController();
|
||||
attachLifecycleListener(controller);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.tag("root")
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.get().isChangingConfigurations = true;
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
mActivityController.saveInstanceState(bundle);
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.saveViewStateCalls++;
|
||||
expectedCallState.saveInstanceStateCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.stop();
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.destroy();
|
||||
expectedCallState.destroyViewCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
createActivityController(bundle);
|
||||
controller = (TestController)mRouter.getControllerWithTag("root");
|
||||
|
||||
expectedCallState.restoreInstanceStateCalls++;
|
||||
expectedCallState.restoreViewStateCalls++;
|
||||
expectedCallState.changeStartCalls++;
|
||||
expectedCallState.changeEndCalls++;
|
||||
expectedCallState.createViewCalls++;
|
||||
|
||||
// Lifecycle listener isn't attached during restore, grab the current views from the controller for this stuff...
|
||||
mCurrentCallState.restoreInstanceStateCalls = controller.currentCallState.restoreInstanceStateCalls;
|
||||
mCurrentCallState.restoreViewStateCalls = controller.currentCallState.restoreViewStateCalls;
|
||||
mCurrentCallState.changeStartCalls = controller.currentCallState.changeStartCalls;
|
||||
mCurrentCallState.changeEndCalls = controller.currentCallState.changeEndCalls;
|
||||
mCurrentCallState.createViewCalls = controller.currentCallState.createViewCalls;
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.resume();
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycleWithActivityBackground() {
|
||||
TestController controller = new TestController();
|
||||
attachLifecycleListener(controller);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
mActivityController.saveInstanceState(bundle);
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.saveInstanceStateCalls++;
|
||||
expectedCallState.saveViewStateCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.resume();
|
||||
expectedCallState.createViewCalls++;
|
||||
expectedCallState.restoreViewStateCalls++;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycleCallOrder() {
|
||||
final TestController testController = new TestController();
|
||||
final CallState callState = new CallState();
|
||||
|
||||
testController.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void preCreateView(@NonNull Controller controller) {
|
||||
callState.createViewCalls++;
|
||||
Assert.assertEquals(1, callState.createViewCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.attachCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.detachCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyViewCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCreateView(@NonNull Controller controller, @NonNull View view) {
|
||||
callState.createViewCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.attachCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.detachCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyViewCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preAttach(@NonNull Controller controller, @NonNull View view) {
|
||||
callState.attachCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(1, callState.attachCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.detachCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyViewCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAttach(@NonNull Controller controller, @NonNull View view) {
|
||||
callState.attachCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.detachCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyViewCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDetach(@NonNull Controller controller, @NonNull View view) {
|
||||
callState.detachCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(1, callState.detachCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyViewCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDetach(@NonNull Controller controller, @NonNull View view) {
|
||||
callState.detachCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.detachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyViewCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDestroyView(@NonNull Controller controller, @NonNull View view) {
|
||||
callState.destroyViewCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.detachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(1, callState.destroyViewCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDestroyView(@NonNull Controller controller) {
|
||||
callState.destroyViewCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.detachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.destroyViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(0, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preDestroy(@NonNull Controller controller) {
|
||||
callState.destroyCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.detachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.destroyViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(1, callState.destroyCalls);
|
||||
Assert.assertEquals(0, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDestroy(@NonNull Controller controller) {
|
||||
callState.destroyCalls++;
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.createViewCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.attachCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.detachCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.detachCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.destroyViewCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.destroyViewCalls);
|
||||
|
||||
Assert.assertEquals(2, callState.destroyCalls);
|
||||
Assert.assertEquals(1, testController.currentCallState.destroyCalls);
|
||||
}
|
||||
});
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(testController)
|
||||
.pushChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.popChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.removeView(from);
|
||||
ViewUtils.setAttached(from, false);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.build());
|
||||
|
||||
mRouter.popController(testController);
|
||||
|
||||
Assert.assertEquals(2, callState.createViewCalls);
|
||||
Assert.assertEquals(2, callState.attachCalls);
|
||||
Assert.assertEquals(2, callState.detachCalls);
|
||||
Assert.assertEquals(2, callState.destroyViewCalls);
|
||||
Assert.assertEquals(2, callState.destroyCalls);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChildLifecycle() {
|
||||
Controller parent = new TestController();
|
||||
mRouter.pushController(RouterTransaction.builder(parent)
|
||||
.pushChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.build());
|
||||
|
||||
TestController child = new TestController();
|
||||
attachLifecycleListener(child);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, child))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, child))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.removeChildController(child);
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChildLifecycle2() {
|
||||
Controller parent = new TestController();
|
||||
mRouter.pushController(RouterTransaction.builder(parent)
|
||||
.pushChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.popChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.removeView(from);
|
||||
ViewUtils.setAttached(from, false);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.build());
|
||||
|
||||
TestController child = new TestController();
|
||||
attachLifecycleListener(child);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, child))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, child))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
mRouter.popCurrentController();
|
||||
ViewUtils.setAttached(child.getView(), false);
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyViewCalls++;
|
||||
expectedCallState.destroyCalls++;
|
||||
assertCalls(expectedCallState, child);
|
||||
}
|
||||
|
||||
private ChangeHandler getPushHandler(final CallState expectedCallState, final TestController controller) {
|
||||
return new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
expectedCallState.changeStartCalls++;
|
||||
expectedCallState.createViewCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
|
||||
expectedCallState.attachCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
changeListener.onChangeCompleted();
|
||||
|
||||
expectedCallState.changeEndCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private ChangeHandler getPopHandler(final CallState expectedCallState, final TestController controller) {
|
||||
return new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
expectedCallState.changeStartCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
container.removeView(from);
|
||||
ViewUtils.setAttached(from, false);
|
||||
|
||||
expectedCallState.destroyViewCalls++;
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
changeListener.onChangeCompleted();
|
||||
|
||||
expectedCallState.changeEndCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void assertCalls(CallState callState, TestController controller) {
|
||||
Assert.assertEquals("Expected call counts and controller call counts do not match.", callState, controller.currentCallState);
|
||||
Assert.assertEquals("Expected call counts and lifecycle call counts do not match.", callState, mCurrentCallState);
|
||||
}
|
||||
|
||||
private void attachLifecycleListener(Controller controller) {
|
||||
controller.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void onChangeStart(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
mCurrentCallState.changeStartCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
mCurrentCallState.changeEndCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCreateView(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.createViewCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAttach(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.attachCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDestroyView(@NonNull Controller controller) {
|
||||
mCurrentCallState.destroyViewCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDetach(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.detachCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDestroy(@NonNull Controller controller) {
|
||||
mCurrentCallState.destroyCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Controller controller, @NonNull Bundle outState) {
|
||||
mCurrentCallState.saveInstanceStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(@NonNull Controller controller, @NonNull Bundle savedInstanceState) {
|
||||
mCurrentCallState.restoreInstanceStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveViewState(@NonNull Controller controller, @NonNull Bundle outState) {
|
||||
mCurrentCallState.saveViewStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreViewState(@NonNull Controller controller, @NonNull Bundle savedViewState) {
|
||||
mCurrentCallState.restoreViewStateCalls++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface ChangeHandlerListener {
|
||||
void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener);
|
||||
}
|
||||
|
||||
public static class ChangeHandler extends ControllerChangeHandler {
|
||||
|
||||
private ChangeHandlerListener mListener;
|
||||
|
||||
public ChangeHandler() { }
|
||||
|
||||
public ChangeHandler(ChangeHandlerListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
mListener.performChange(container, from, to, isPush, changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +1,13 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.bluelinelabs.conductor.Controller.LifecycleListener;
|
||||
import com.bluelinelabs.conductor.Controller.RetainViewMode;
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler.ControllerChangeCompletedListener;
|
||||
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@@ -26,14 +22,11 @@ import org.robolectric.util.ActivityController;
|
||||
@Config(manifest = Config.NONE)
|
||||
public class ControllerTests {
|
||||
|
||||
private Application mApplication;
|
||||
private ActivityController<TestActivity> mActivityController;
|
||||
private Router mRouter;
|
||||
|
||||
private CallState mCurrentCallState;
|
||||
|
||||
public void createActivityController(Bundle savedInstanceState) {
|
||||
mActivityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).withApplication(mApplication).start();
|
||||
mActivityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).start();
|
||||
|
||||
@IdRes int containerId = 4;
|
||||
FrameLayout routerContainer = new FrameLayout(mActivityController.get());
|
||||
@@ -47,233 +40,7 @@ public class ControllerTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mApplication = new Application();
|
||||
|
||||
createActivityController(null);
|
||||
|
||||
mCurrentCallState = new CallState();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalLifecycle() {
|
||||
TestController controller = new TestController();
|
||||
attachLifecycleListener(controller);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mRouter.popCurrentController();
|
||||
|
||||
Assert.assertNull(controller.getView());
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycleWithActivityDestroy() {
|
||||
TestController controller = new TestController();
|
||||
attachLifecycleListener(controller);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.stop();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.destroy();
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyViewCalls++;
|
||||
expectedCallState.destroyCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycleWithActivityConfigurationChange() {
|
||||
TestController controller = new TestController();
|
||||
attachLifecycleListener(controller);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.tag("root")
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.get().isChangingConfigurations = true;
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
mActivityController.saveInstanceState(bundle);
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.saveViewStateCalls++;
|
||||
expectedCallState.saveInstanceStateCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.stop();
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.destroy();
|
||||
expectedCallState.destroyViewCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
createActivityController(bundle);
|
||||
controller = (TestController)mRouter.getControllerWithTag("root");
|
||||
|
||||
expectedCallState.restoreInstanceStateCalls++;
|
||||
expectedCallState.restoreViewStateCalls++;
|
||||
expectedCallState.changeStartCalls++;
|
||||
expectedCallState.changeEndCalls++;
|
||||
expectedCallState.createViewCalls++;
|
||||
|
||||
// Lifecycle listener isn't attached during restore, grab the current views from the controller for this stuff...
|
||||
mCurrentCallState.restoreInstanceStateCalls = controller.currentCallState.restoreInstanceStateCalls;
|
||||
mCurrentCallState.restoreViewStateCalls = controller.currentCallState.restoreViewStateCalls;
|
||||
mCurrentCallState.changeStartCalls = controller.currentCallState.changeStartCalls;
|
||||
mCurrentCallState.changeEndCalls = controller.currentCallState.changeEndCalls;
|
||||
mCurrentCallState.createViewCalls = controller.currentCallState.createViewCalls;
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.resume();
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycleWithActivityBackground() {
|
||||
TestController controller = new TestController();
|
||||
attachLifecycleListener(controller);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(controller)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, controller))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.pause();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
mActivityController.saveInstanceState(bundle);
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.saveInstanceStateCalls++;
|
||||
expectedCallState.saveViewStateCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
mActivityController.resume();
|
||||
expectedCallState.createViewCalls++;
|
||||
expectedCallState.restoreViewStateCalls++;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChildLifecycle() {
|
||||
Controller parent = new TestController();
|
||||
mRouter.pushController(RouterTransaction.builder(parent)
|
||||
.pushChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.build());
|
||||
|
||||
TestController child = new TestController();
|
||||
attachLifecycleListener(child);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, child))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, child))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.removeChildController(child);
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChildLifecycle2() {
|
||||
Controller parent = new TestController();
|
||||
mRouter.pushController(RouterTransaction.builder(parent)
|
||||
.pushChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.popChangeHandler(new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
container.removeView(from);
|
||||
ViewUtils.setAttached(from, false);
|
||||
changeListener.onChangeCompleted();
|
||||
}
|
||||
}))
|
||||
.build());
|
||||
|
||||
TestController child = new TestController();
|
||||
attachLifecycleListener(child);
|
||||
|
||||
CallState expectedCallState = new CallState();
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID)
|
||||
.pushChangeHandler(getPushHandler(expectedCallState, child))
|
||||
.popChangeHandler(getPopHandler(expectedCallState, child))
|
||||
.build()
|
||||
);
|
||||
|
||||
assertCalls(expectedCallState, child);
|
||||
|
||||
mRouter.popCurrentController();
|
||||
ViewUtils.setAttached(child.getView(), false);
|
||||
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyViewCalls++;
|
||||
expectedCallState.destroyCalls++;
|
||||
assertCalls(expectedCallState, child);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -304,132 +71,205 @@ public class ControllerTests {
|
||||
Assert.assertNull(controller.getView());
|
||||
}
|
||||
|
||||
private ChangeHandler getPushHandler(final CallState expectedCallState, final TestController controller) {
|
||||
return new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
expectedCallState.changeStartCalls++;
|
||||
expectedCallState.createViewCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
@Test
|
||||
public void testActivityResult() {
|
||||
TestController controller = new TestController();
|
||||
CallState expectedCallState = new CallState(true);
|
||||
|
||||
container.addView(to);
|
||||
ViewUtils.setAttached(to, true);
|
||||
mRouter.pushController(RouterTransaction.builder(controller).build());
|
||||
ViewUtils.setAttached(controller.getView(), true);
|
||||
|
||||
expectedCallState.attachCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
// Ensure that calling onActivityResult w/o requesting a result doesn't do anything
|
||||
mRouter.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
changeListener.onChangeCompleted();
|
||||
// Ensure starting an activity for result gets us the result back
|
||||
controller.startActivityForResult(new Intent("action"), 1);
|
||||
mRouter.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
expectedCallState.onActivityResultCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
expectedCallState.changeEndCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
});
|
||||
// Ensure requesting a result w/o calling startActivityForResult works
|
||||
controller.registerForActivityResult(2);
|
||||
mRouter.onActivityResult(2, Activity.RESULT_OK, null);
|
||||
expectedCallState.onActivityResultCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
private ChangeHandler getPopHandler(final CallState expectedCallState, final TestController controller) {
|
||||
return new ChangeHandler(new ChangeHandlerListener() {
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
expectedCallState.changeStartCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
container.removeView(from);
|
||||
ViewUtils.setAttached(from, false);
|
||||
@Test
|
||||
public void testActivityResultForChild() {
|
||||
TestController parent = new TestController();
|
||||
TestController child = new TestController();
|
||||
|
||||
expectedCallState.destroyViewCalls++;
|
||||
expectedCallState.detachCalls++;
|
||||
expectedCallState.destroyCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
mRouter.pushController(RouterTransaction.builder(parent).build());
|
||||
ViewUtils.setAttached(parent.getView(), true);
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID).build());
|
||||
ViewUtils.setAttached(child.getView(), true);
|
||||
|
||||
changeListener.onChangeCompleted();
|
||||
CallState childExpectedCallState = new CallState(true);
|
||||
CallState parentExpectedCallState = new CallState(true);
|
||||
|
||||
expectedCallState.changeEndCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
});
|
||||
// Ensure that calling onActivityResult w/o requesting a result doesn't do anything
|
||||
mRouter.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure starting an activity for result gets us the result back
|
||||
child.startActivityForResult(new Intent("action"), 1);
|
||||
mRouter.onActivityResult(1, Activity.RESULT_OK, null);
|
||||
childExpectedCallState.onActivityResultCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure requesting a result w/o calling startActivityForResult works
|
||||
child.registerForActivityResult(2);
|
||||
mRouter.onActivityResult(2, Activity.RESULT_OK, null);
|
||||
childExpectedCallState.onActivityResultCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPermissionResult() {
|
||||
final String[] requestedPermissions = new String[] {"test"};
|
||||
|
||||
TestController controller = new TestController();
|
||||
CallState expectedCallState = new CallState(true);
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller).build());
|
||||
ViewUtils.setAttached(controller.getView(), true);
|
||||
|
||||
// Ensure that calling handleRequestedPermission w/o requesting a result doesn't do anything
|
||||
mRouter.onRequestPermissionsResult("anotherId", 1, requestedPermissions, new int[] {1});
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure requesting the permission gets us the result back
|
||||
try {
|
||||
controller.requestPermissions(requestedPermissions, 1);
|
||||
} catch (NoSuchMethodError ignored) { }
|
||||
|
||||
mRouter.onRequestPermissionsResult(controller.getInstanceId(), 1, requestedPermissions, new int[] {1});
|
||||
expectedCallState.onRequestPermissionsResultCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPermissionResultForChild() {
|
||||
final String[] requestedPermissions = new String[] {"test"};
|
||||
|
||||
TestController parent = new TestController();
|
||||
TestController child = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(parent).build());
|
||||
ViewUtils.setAttached(parent.getView(), true);
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID).build());
|
||||
ViewUtils.setAttached(child.getView(), true);
|
||||
|
||||
CallState childExpectedCallState = new CallState(true);
|
||||
CallState parentExpectedCallState = new CallState(true);
|
||||
|
||||
// Ensure that calling handleRequestedPermission w/o requesting a result doesn't do anything
|
||||
mRouter.onRequestPermissionsResult("anotherId", 1, requestedPermissions, new int[] {1});
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure requesting the permission gets us the result back
|
||||
try {
|
||||
child.requestPermissions(requestedPermissions, 1);
|
||||
} catch (NoSuchMethodError ignored) { }
|
||||
|
||||
mRouter.onRequestPermissionsResult(child.getInstanceId(), 1, requestedPermissions, new int[] {1});
|
||||
childExpectedCallState.onRequestPermissionsResultCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionsMenu() {
|
||||
TestController controller = new TestController();
|
||||
CallState expectedCallState = new CallState(true);
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(controller).build());
|
||||
ViewUtils.setAttached(controller.getView(), true);
|
||||
|
||||
// Ensure that calling onCreateOptionsMenu w/o declaring that we have one doesn't do anything
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure calling onCreateOptionsMenu with a menu works
|
||||
controller.setHasOptionsMenu(true);
|
||||
|
||||
// Ensure it'll still get called back next time onCreateOptionsMenu is called
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
expectedCallState.createOptionsMenuCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure we stop getting them when we hide it
|
||||
controller.setOptionsMenuHidden(true);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure we get the callback them when we un-hide it
|
||||
controller.setOptionsMenuHidden(false);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
expectedCallState.createOptionsMenuCalls++;
|
||||
assertCalls(expectedCallState, controller);
|
||||
|
||||
// Ensure we don't get the callback when we no longer have a menu
|
||||
controller.setHasOptionsMenu(false);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
assertCalls(expectedCallState, controller);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionsMenuForChild() {
|
||||
TestController parent = new TestController();
|
||||
TestController child = new TestController();
|
||||
|
||||
mRouter.pushController(RouterTransaction.builder(parent).build());
|
||||
ViewUtils.setAttached(parent.getView(), true);
|
||||
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID).build());
|
||||
ViewUtils.setAttached(child.getView(), true);
|
||||
|
||||
CallState childExpectedCallState = new CallState(true);
|
||||
CallState parentExpectedCallState = new CallState(true);
|
||||
|
||||
// Ensure that calling onCreateOptionsMenu w/o declaring that we have one doesn't do anything
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure calling onCreateOptionsMenu with a menu works
|
||||
child.setHasOptionsMenu(true);
|
||||
|
||||
// Ensure it'll still get called back next time onCreateOptionsMenu is called
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
childExpectedCallState.createOptionsMenuCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure we stop getting them when we hide it
|
||||
child.setOptionsMenuHidden(true);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure we get the callback them when we un-hide it
|
||||
child.setOptionsMenuHidden(false);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
childExpectedCallState.createOptionsMenuCalls++;
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
|
||||
// Ensure we don't get the callback when we no longer have a menu
|
||||
child.setHasOptionsMenu(false);
|
||||
mRouter.onCreateOptionsMenu(null, null);
|
||||
assertCalls(childExpectedCallState, child);
|
||||
assertCalls(parentExpectedCallState, parent);
|
||||
}
|
||||
|
||||
private void assertCalls(CallState callState, TestController controller) {
|
||||
Assert.assertEquals("Expected call counts and controller call counts do not match.", callState, controller.currentCallState);
|
||||
Assert.assertEquals("Expected call counts and lifecycle call counts do not match.", callState, mCurrentCallState);
|
||||
}
|
||||
|
||||
private void attachLifecycleListener(Controller controller) {
|
||||
controller.addLifecycleListener(new LifecycleListener() {
|
||||
@Override
|
||||
public void onChangeStart(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
mCurrentCallState.changeStartCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
|
||||
mCurrentCallState.changeEndCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCreateView(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.createViewCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAttach(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.attachCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDestroyView(@NonNull Controller controller) {
|
||||
mCurrentCallState.destroyViewCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDetach(@NonNull Controller controller, @NonNull View view) {
|
||||
mCurrentCallState.detachCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDestroy(@NonNull Controller controller) {
|
||||
mCurrentCallState.destroyCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Controller controller, @NonNull Bundle outState) {
|
||||
mCurrentCallState.saveInstanceStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(@NonNull Controller controller, @NonNull Bundle savedInstanceState) {
|
||||
mCurrentCallState.restoreInstanceStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveViewState(@NonNull Controller controller, @NonNull Bundle outState) {
|
||||
mCurrentCallState.saveViewStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreViewState(@NonNull Controller controller, @NonNull Bundle savedViewState) {
|
||||
mCurrentCallState.restoreViewStateCalls++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface ChangeHandlerListener {
|
||||
void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener);
|
||||
}
|
||||
|
||||
public static class ChangeHandler extends ControllerChangeHandler {
|
||||
|
||||
private ChangeHandlerListener mListener;
|
||||
|
||||
public ChangeHandler() { }
|
||||
|
||||
public ChangeHandler(ChangeHandlerListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performChange(@NonNull ViewGroup container, View from, View to, boolean isPush, @NonNull ControllerChangeCompletedListener changeListener) {
|
||||
mListener.performChange(container, from, to, isPush, changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.bluelinelabs.conductor;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -96,4 +99,26 @@ public class TestController extends Controller {
|
||||
|
||||
currentCallState.restoreInstanceStateCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
currentCallState.onActivityResultCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
|
||||
currentCallState.onRequestPermissionsResultCalls++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
currentCallState.createOptionsMenuCalls++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-6
@@ -14,6 +14,10 @@ android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.2"
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
@@ -41,12 +45,8 @@ dependencies {
|
||||
|
||||
compile rootProject.ext.butterknife
|
||||
|
||||
compile 'com.bluelinelabs:conductor:' + rootProject.ext.publishedVersionName
|
||||
compile 'com.bluelinelabs:conductor-support:' + rootProject.ext.publishedVersionName
|
||||
compile 'com.bluelinelabs:conductor-rxlifecycle:' + rootProject.ext.publishedVersionName
|
||||
|
||||
// compile project(':conductor-support')
|
||||
// compile project(':conductor-rxlifecycle')
|
||||
compile project(':conductor-support')
|
||||
compile project(':conductor-rxlifecycle')
|
||||
|
||||
debugCompile rootProject.ext.leakCanary
|
||||
releaseCompile rootProject.ext.leakCanaryNoOp
|
||||
|
||||
@@ -24,7 +24,7 @@ public class PagerController extends BaseController {
|
||||
@Bind(R.id.tab_layout) TabLayout mTabLayout;
|
||||
@Bind(R.id.view_pager) ViewPager mViewPager;
|
||||
|
||||
private ControllerPagerAdapter mPagerAdapter;
|
||||
private final ControllerPagerAdapter mPagerAdapter;
|
||||
|
||||
public PagerController() {
|
||||
mPagerAdapter = new ControllerPagerAdapter(this) {
|
||||
@@ -66,6 +66,12 @@ public class PagerController extends BaseController {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroyView(View view) {
|
||||
mViewPager.setAdapter(null);
|
||||
super.onDestroyView(view);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
||||
|
||||
+1
-5
@@ -4,10 +4,6 @@ ext {
|
||||
targetSdkVersion = 23
|
||||
buildToolsVersion = '23.0.2'
|
||||
|
||||
versionCode = 1
|
||||
versionName = '1.1.4'
|
||||
publishedVersionName = '1.1.3'
|
||||
|
||||
supportV4 = 'com.android.support:support-v4:23.1.1'
|
||||
supportDesign = 'com.android.support:design:23.1.1'
|
||||
supportAnnotations = 'com.android.support:support-annotations:23.1.1'
|
||||
@@ -20,7 +16,7 @@ ext {
|
||||
|
||||
rxJava = 'io.reactivex:rxjava:1.1.0'
|
||||
rxAndroid = 'io.reactivex:rxandroid:1.1.0'
|
||||
rxLifecycle = 'com.trello:rxlifecycle:0.5.0'
|
||||
rxLifecycle = 'com.trello:rxlifecycle:0.6.0'
|
||||
|
||||
junit = 'junit:junit:4.11'
|
||||
roboelectric = 'org.robolectric:robolectric:3.0'
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2013 Chris Banes
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'signing'
|
||||
|
||||
def isReleaseBuild() {
|
||||
return VERSION_NAME.contains("SNAPSHOT") == false
|
||||
}
|
||||
|
||||
def getReleaseRepositoryUrl() {
|
||||
return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL :
|
||||
"https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
||||
}
|
||||
|
||||
def getSnapshotRepositoryUrl() {
|
||||
return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL :
|
||||
"https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
}
|
||||
|
||||
def getRepositoryUsername() {
|
||||
return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
|
||||
}
|
||||
|
||||
def getRepositoryPassword() {
|
||||
return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
|
||||
}
|
||||
|
||||
afterEvaluate { project ->
|
||||
uploadArchives {
|
||||
repositories {
|
||||
mavenDeployer {
|
||||
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
|
||||
|
||||
pom.groupId = GROUP
|
||||
pom.artifactId = POM_ARTIFACT_ID
|
||||
pom.version = VERSION_NAME
|
||||
|
||||
repository(url: getReleaseRepositoryUrl()) {
|
||||
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
|
||||
}
|
||||
snapshotRepository(url: getSnapshotRepositoryUrl()) {
|
||||
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
|
||||
}
|
||||
|
||||
pom.project {
|
||||
name POM_NAME
|
||||
packaging POM_PACKAGING
|
||||
description POM_DESCRIPTION
|
||||
url POM_URL
|
||||
|
||||
scm {
|
||||
url POM_SCM_URL
|
||||
connection POM_SCM_CONNECTION
|
||||
developerConnection POM_SCM_DEV_CONNECTION
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name POM_LICENCE_NAME
|
||||
url POM_LICENCE_URL
|
||||
distribution POM_LICENCE_DIST
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id POM_DEVELOPER_ID
|
||||
name POM_DEVELOPER_NAME
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Resolve dependencies to other modules
|
||||
pom.whenConfigured { pom ->
|
||||
pom.dependencies.findAll { dep -> dep.groupId == rootProject.name }.collect { dep ->
|
||||
dep.groupId = pom.groupId = project.GROUP
|
||||
dep.version = pom.version = project.VERSION_NAME
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
|
||||
sign configurations.archives
|
||||
}
|
||||
|
||||
task androidJavadocs(type: Javadoc) {
|
||||
source = android.sourceSets.main.java.srcDirs
|
||||
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
|
||||
failOnError = false
|
||||
}
|
||||
|
||||
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
|
||||
classifier = 'javadoc'
|
||||
from androidJavadocs.destinationDir
|
||||
}
|
||||
|
||||
task androidSourcesJar(type: Jar) {
|
||||
classifier = 'sources'
|
||||
from android.sourceSets.main.java.sourceFiles
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives androidSourcesJar
|
||||
archives androidJavadocsJar
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
VERSION_NAME=1.1.6-SNAPSHOT
|
||||
VERSION_CODE=2
|
||||
GROUP=com.bluelinelabs
|
||||
|
||||
POM_DESCRIPTION=A small, yet full-featured framework that allows building View-based Android applications
|
||||
POM_URL=https://github.com/bluelinelabs/Conductor
|
||||
POM_SCM_URL=https://github.com/bluelinelabs/Conductor
|
||||
POM_SCM_CONNECTION=scm:git:https://github.com/bluelinelabs/Conductor
|
||||
POM_SCM_DEV_CONNECTION=scm:git:https://github.com/bluelinelabs/Conductor
|
||||
POM_LICENCE_NAME=The Apache Software License, Version 2.0
|
||||
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
|
||||
POM_LICENCE_DIST=repo
|
||||
POM_DEVELOPER_ID=erickuck
|
||||
POM_DEVELOPER_NAME=Eric Kuck
|
||||
Reference in New Issue
Block a user