Compare commits

...

12 Commits

Author SHA1 Message Date
Eric Kuck e028ed42da Version bump 2016-04-16 14:22:38 -05:00
Eric Kuck 43dc561ac2 Fixed up some save/restore view state stuff (incl. tests) 2016-04-16 13:51:37 -05:00
Eric Kuck 217b55090a Added test for backgrounding the host activity 2016-04-16 13:18:24 -05:00
Eric Kuck 5c8b78e41d Fixed orientation change test 2016-04-16 12:25:45 -05:00
Eric Kuck 899dd70d50 Merge pull request #25 from sockeqwe/viewStateListener
added methods to lifecyclelistener for saving/restoring viewstate
2016-04-16 12:04:51 -05:00
Eric Kuck d945571d31 Improved controller lifecycle test coverage (and clarity) 2016-04-16 12:04:20 -05:00
Hannes Dorfmann b7a4386d22 Renamed parameter of onRestoreViewState() to savedViewState 2016-04-16 14:01:41 +02:00
Hannes Dorfmann b117307340 added methods to lifecyclelistener for saving/restoring viewstate 2016-04-15 19:52:43 +02:00
Eric Kuck b8ccf3623f Fixed onRestoreState call ordering for controllers with parent/child relationships 2016-04-14 14:20:56 -05:00
Eric Kuck 495145b72b Router, Activity, target controller, etc is all now available in onRestoreInstanceState 2016-04-13 15:39:09 -05:00
Eric Kuck 99e25d65f2 Merge pull request #20 from adi1133/develop
Fix crash caused by recreating static nested classes using reflection
2016-04-12 16:41:05 -05:00
Adi Pascu 2619d13c8d Fix crash caused by recreating static nested classes using reflection 2016-04-12 23:49:10 +03:00
14 changed files with 504 additions and 90 deletions
+3 -3
View File
@@ -20,14 +20,14 @@ Conductor is architecture-agnostic and does not try to force any design decision
## Installation
```gradle
compile 'com.bluelinelabs:conductor:1.1.3'
compile 'com.bluelinelabs:conductor:1.1.4'
// If you want the components that go along with
// Android's support libraries (currently just a PagerAdapter):
compile 'com.bluelinelabs:conductor-support:1.1.3'
compile 'com.bluelinelabs:conductor-support:1.1.4'
// If you want RxJava/RxAndroid lifecycle support:
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.3'
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.4'
```
## Components to Know
@@ -54,6 +54,7 @@ public abstract class Controller {
private final Bundle mArgs;
private Bundle mViewState;
private Bundle mSavedInstanceState;
private boolean mIsBeingDestroyed;
private boolean mDestroyed;
private boolean mAttached;
@@ -66,6 +67,7 @@ public abstract class Controller {
private String mInstanceId;
private String mTargetInstanceId;
private boolean mNeedsAttach;
private boolean mHasSavedViewState;
private ControllerChangeHandler mOverriddenPushHandler;
private ControllerChangeHandler mOverriddenPopHandler;
private RetainViewMode mRetainViewMode = RetainViewMode.RELEASE_DETACH;
@@ -646,15 +648,21 @@ public abstract class Controller {
}
final void setRouter(@NonNull Router router) {
mRouter = router;
if (mRouter != router) {
mRouter = router;
for (RouterRequiringFunc listener : mOnRouterSetListeners) {
listener.execute();
}
mOnRouterSetListeners.clear();
performOnRestoreInstanceState();
for (ChildControllerTransaction child : mChildControllers) {
child.controller.setRouter(router);
for (RouterRequiringFunc listener : mOnRouterSetListeners) {
listener.execute();
}
mOnRouterSetListeners.clear();
for (ChildControllerTransaction child : mChildControllers) {
child.controller.setRouter(router);
}
} else {
performOnRestoreInstanceState();
}
}
@@ -739,6 +747,8 @@ public abstract class Controller {
}
private void attach(@NonNull View view) {
mHasSavedViewState = false;
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
lifecycleListener.preAttach(this, view);
}
@@ -797,7 +807,7 @@ public abstract class Controller {
private void removeViewReference() {
if (mView != null) {
if (!mIsBeingDestroyed) {
if (!mIsBeingDestroyed && !mHasSavedViewState) {
saveViewState(mView);
}
@@ -892,6 +902,8 @@ public abstract class Controller {
}
final void saveViewState(@NonNull View view) {
mHasSavedViewState = true;
mViewState = new Bundle();
SparseArray<Parcelable> hierarchyState = new SparseArray<>();
@@ -907,6 +919,10 @@ public abstract class Controller {
child.controller.saveViewState(child.controller.mView);
}
}
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
lifecycleListener.onSaveViewState(this, mViewState);
}
}
final void restoreViewState(@NonNull View view) {
@@ -919,6 +935,10 @@ public abstract class Controller {
child.controller.restoreViewState(child.controller.mView);
}
}
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
lifecycleListener.onRestoreViewState(this, mViewState);
}
}
}
@@ -927,8 +947,12 @@ public abstract class Controller {
detach(mView, mIsBeingDestroyed);
}
if (!mHasSavedViewState && mView != null) {
saveViewState(mView);
}
Bundle outState = new Bundle();
outState.putString(KEY_CLASS_NAME, getClass().getCanonicalName());
outState.putString(KEY_CLASS_NAME, getClass().getName());
outState.putBundle(KEY_VIEW_STATE, mViewState);
outState.putBundle(KEY_ARGS, mArgs);
outState.putString(KEY_INSTANCE_ID, mInstanceId);
@@ -975,11 +999,19 @@ public abstract class Controller {
addChildController(new ChildControllerTransaction(childBundle));
}
Bundle savedState = savedInstanceState.getBundle(KEY_SAVED_STATE);
onRestoreInstanceState(savedState);
mSavedInstanceState = savedInstanceState.getBundle(KEY_SAVED_STATE);
performOnRestoreInstanceState();
}
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
lifecycleListener.onRestoreInstanceState(this, savedState);
private void performOnRestoreInstanceState() {
if (mSavedInstanceState != null && mRouter != null) {
onRestoreInstanceState(mSavedInstanceState);
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
lifecycleListener.onRestoreInstanceState(this, mSavedInstanceState);
}
mSavedInstanceState = null;
}
}
@@ -1074,6 +1106,9 @@ public abstract class Controller {
public void onSaveInstanceState(@NonNull Controller controller, @NonNull Bundle outState) { }
public void onRestoreInstanceState(@NonNull Controller controller, @NonNull Bundle savedInstanceState) { }
public void onSaveViewState(@NonNull Controller controller, @NonNull Bundle outState) { }
public void onRestoreViewState(@NonNull Controller controller, @NonNull Bundle savedViewState) { }
}
}
@@ -53,7 +53,7 @@ public abstract class ControllerChangeHandler {
final Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putString(KEY_CLASS_NAME, getClass().getCanonicalName());
bundle.putString(KEY_CLASS_NAME, getClass().getName());
Bundle savedState = new Bundle();
saveToBundle(savedState);
@@ -403,6 +403,11 @@ public class Router {
public final void onRestoreInstanceState(Bundle savedInstanceState) {
mBackStack.restoreInstanceState(savedInstanceState);
Iterator<RouterTransaction> backstackIterator = mBackStack.reverseIterator();
while (backstackIterator.hasNext()) {
backstackIterator.next().controller.setRouter(this);
}
}
public final void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
@@ -50,8 +50,8 @@ public class TransitionChangeHandlerCompat extends ControllerChangeHandler {
public void saveToBundle(@NonNull Bundle bundle) {
super.saveToBundle(bundle);
bundle.putString(KEY_TRANSITION_HANDLER_CLASS, mTransitionChangeHandler.getClass().getCanonicalName());
bundle.putString(KEY_FALLBACK_HANDLER_CLASS, mFallbackChangeHandler.getClass().getCanonicalName());
bundle.putString(KEY_TRANSITION_HANDLER_CLASS, mTransitionChangeHandler.getClass().getName());
bundle.putString(KEY_FALLBACK_HANDLER_CLASS, mFallbackChangeHandler.getClass().getName());
Bundle transitionBundle = new Bundle();
mTransitionChangeHandler.saveToBundle(transitionBundle);
@@ -61,13 +61,16 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
Router router = mRouterMap.get(getRouterHashKey(container));
if (router == null) {
router = new Router();
router.setHost(this, container);
if (savedInstanceState != null) {
router.onRestoreInstanceState(savedInstanceState);
}
mRouterMap.put(getRouterHashKey(container), router);
} else {
router.setHost(this, container);
}
router.setHost(this, container);
return router;
}
@@ -0,0 +1,138 @@
package com.bluelinelabs.conductor;
import android.os.Parcel;
import android.os.Parcelable;
public class CallState implements Parcelable {
public int changeStartCalls;
public int changeEndCalls;
public int createViewCalls;
public int attachCalls;
public int destroyViewCalls;
public int detachCalls;
public int destroyCalls;
public int saveInstanceStateCalls;
public int restoreInstanceStateCalls;
public int saveViewStateCalls;
public int restoreViewStateCalls;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
CallState callState = (CallState)o;
if (changeStartCalls != callState.changeStartCalls) {
return false;
}
if (changeEndCalls != callState.changeEndCalls) {
return false;
}
if (createViewCalls != callState.createViewCalls) {
return false;
}
if (attachCalls != callState.attachCalls) {
return false;
}
if (destroyViewCalls != callState.destroyViewCalls) {
return false;
}
if (detachCalls != callState.detachCalls) {
return false;
}
if (destroyCalls != callState.destroyCalls) {
return false;
}
if (saveInstanceStateCalls != callState.saveInstanceStateCalls) {
return false;
}
if (saveViewStateCalls != callState.saveViewStateCalls) {
return false;
}
if (restoreViewStateCalls != callState.restoreViewStateCalls) {
return false;
}
return restoreInstanceStateCalls == callState.restoreInstanceStateCalls;
}
@Override
public int hashCode() {
int result = changeStartCalls;
result = 31 * result + changeEndCalls;
result = 31 * result + createViewCalls;
result = 31 * result + attachCalls;
result = 31 * result + destroyViewCalls;
result = 31 * result + detachCalls;
result = 31 * result + destroyCalls;
result = 31 * result + saveInstanceStateCalls;
result = 31 * result + restoreInstanceStateCalls;
result = 31 * result + saveViewStateCalls;
result = 31 * result + restoreViewStateCalls;
return result;
}
@Override
public String toString() {
return "\nCallState{" +
"\n changeStartCalls=" + changeStartCalls +
"\n changeEndCalls=" + changeEndCalls +
"\n createViewCalls=" + createViewCalls +
"\n attachCalls=" + attachCalls +
"\n destroyViewCalls=" + destroyViewCalls +
"\n detachCalls=" + detachCalls +
"\n destroyCalls=" + destroyCalls +
"\n saveInstanceStateCalls=" + saveInstanceStateCalls +
"\n restoreInstanceStateCalls=" + restoreInstanceStateCalls +
"\n saveViewStateCalls=" + saveViewStateCalls +
"\n restoreViewStateCalls=" + restoreViewStateCalls +
"}\n";
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(changeStartCalls);
out.writeInt(changeEndCalls);
out.writeInt(createViewCalls);
out.writeInt(attachCalls);
out.writeInt(destroyViewCalls);
out.writeInt(detachCalls);
out.writeInt(destroyCalls);
out.writeInt(saveInstanceStateCalls);
out.writeInt(restoreInstanceStateCalls);
out.writeInt(saveViewStateCalls);
out.writeInt(restoreViewStateCalls);
}
public static final Parcelable.Creator<CallState> CREATOR = new Parcelable.Creator<CallState>() {
public CallState createFromParcel(Parcel in) {
CallState state = new CallState();
state.changeStartCalls = in.readInt();
state.changeEndCalls = in.readInt();
state.createViewCalls = in.readInt();
state.attachCalls = in.readInt();
state.destroyViewCalls = in.readInt();
state.detachCalls = in.readInt();
state.destroyCalls = in.readInt();
state.saveInstanceStateCalls = in.readInt();
state.restoreInstanceStateCalls = in.readInt();
state.saveViewStateCalls = in.readInt();
state.restoreViewStateCalls = in.readInt();
return state;
}
public CallState[] newArray(int size) {
return new CallState[size];
}
};
}
@@ -1,6 +1,8 @@
package com.bluelinelabs.conductor;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
@@ -24,78 +26,174 @@ import org.robolectric.util.ActivityController;
@Config(manifest = Config.NONE)
public class ControllerTests {
private Application mApplication;
private ActivityController<TestActivity> mActivityController;
private Router mRouter;
private int mChangeStartCalls;
private int mChangeEndCalls;
private int mCreateViewCalls;
private int mAttachCalls;
private int mDestroyViewCalls;
private int mDetachCalls;
private int mDestroyCalls;
private CallState mCurrentCallState;
public void createActivityController(Bundle savedInstanceState) {
mActivityController = Robolectric.buildActivity(TestActivity.class).create(savedInstanceState).withApplication(mApplication).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() {
mActivityController = Robolectric.buildActivity(TestActivity.class).create();
Activity activity = mActivityController.get();
mRouter = Conductor.attachRouter(activity, new FrameLayout(activity), null);
mRouter.setRoot(new TestController());
mApplication = new Application();
mChangeStartCalls = 0;
mChangeEndCalls = 0;
mCreateViewCalls = 0;
mAttachCalls = 0;
mDestroyViewCalls = 0;
mDestroyCalls = 0;
mDestroyCalls = 0;
createActivityController(null);
mCurrentCallState = new CallState();
}
@Test
public void testNormalLifecycle() {
Controller controller = new TestController();
TestController controller = new TestController();
attachLifecycleListener(controller);
assertCalls(0, 0, 0, 0, 0, 0, 0);
CallState expectedCallState = new CallState();
assertCalls(expectedCallState, controller);
mRouter.pushController(RouterTransaction.builder(controller)
.pushChangeHandler(getPushHandler(0, 0, 0, 0, 0, 0, 0))
.popChangeHandler(getPopHandler(1, 1, 1, 1, 0, 0, 0))
.pushChangeHandler(getPushHandler(expectedCallState, controller))
.popChangeHandler(getPopHandler(expectedCallState, controller))
.build()
);
assertCalls(1, 1, 1, 1, 0, 0, 0);
assertCalls(expectedCallState, controller);
mRouter.popCurrentController();
Assert.assertNull(controller.getView());
assertCalls(2, 2, 1, 1, 1, 1, 1);
assertCalls(expectedCallState, controller);
}
@Test
public void testLifecycleWithActivityDestroy() {
Controller controller = new TestController();
TestController controller = new TestController();
attachLifecycleListener(controller);
assertCalls(0, 0, 0, 0, 0, 0, 0);
CallState expectedCallState = new CallState();
assertCalls(expectedCallState, controller);
mRouter.pushController(RouterTransaction.builder(controller)
.pushChangeHandler(getPushHandler(0, 0, 0, 0, 0, 0, 0))
.pushChangeHandler(getPushHandler(expectedCallState, controller))
.build()
);
assertCalls(1, 1, 1, 1, 0, 0, 0);
assertCalls(expectedCallState, controller);
mActivityController.pause();
assertCalls(1, 1, 1, 1, 0, 0, 0);
assertCalls(expectedCallState, controller);
mActivityController.stop();
assertCalls(1, 1, 1, 1, 0, 0, 0);
assertCalls(expectedCallState, controller);
mActivityController.destroy();
assertCalls(1, 1, 1, 1, 1, 1, 1);
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
@@ -112,22 +210,24 @@ public class ControllerTests {
}))
.build());
Controller child = new TestController();
TestController child = new TestController();
attachLifecycleListener(child);
assertCalls(0, 0, 0, 0, 0, 0, 0);
CallState expectedCallState = new CallState();
assertCalls(expectedCallState, child);
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID)
.pushChangeHandler(getPushHandler(0, 0, 0, 0, 0, 0, 0))
.popChangeHandler(getPopHandler(1, 1, 1, 1, 0, 0, 0))
.pushChangeHandler(getPushHandler(expectedCallState, child))
.popChangeHandler(getPopHandler(expectedCallState, child))
.build()
);
assertCalls(1, 1, 1, 1, 0, 0, 0);
assertCalls(expectedCallState, child);
parent.removeChildController(child);
assertCalls(2, 2, 1, 1, 1, 1, 1);
assertCalls(expectedCallState, child);
}
@Test
@@ -152,23 +252,28 @@ public class ControllerTests {
}))
.build());
Controller child = new TestController();
TestController child = new TestController();
attachLifecycleListener(child);
assertCalls(0, 0, 0, 0, 0, 0, 0);
CallState expectedCallState = new CallState();
assertCalls(expectedCallState, child);
parent.addChildController(ChildControllerTransaction.builder(child, TestController.VIEW_ID)
.pushChangeHandler(getPushHandler(0, 0, 0, 0, 0, 0, 0))
.popChangeHandler(getPopHandler(1, 1, 1, 1, 0, 0, 0))
.pushChangeHandler(getPushHandler(expectedCallState, child))
.popChangeHandler(getPopHandler(expectedCallState, child))
.build()
);
assertCalls(1, 1, 1, 1, 0, 0, 0);
assertCalls(expectedCallState, child);
mRouter.popCurrentController();
ViewUtils.setAttached(child.getView(), false);
assertCalls(1, 1, 1, 1, 1, 1, 1);
expectedCallState.detachCalls++;
expectedCallState.destroyViewCalls++;
expectedCallState.destroyCalls++;
assertCalls(expectedCallState, child);
}
@Test
@@ -199,77 +304,110 @@ public class ControllerTests {
Assert.assertNull(controller.getView());
}
private ChangeHandler getPushHandler(final int changeStart, final int changeEnd, final int bindView, final int attach, final int unbindView, final int detach, final int destroy) {
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) {
assertCalls(changeStart + 1, changeEnd, bindView + 1, attach, unbindView, detach, destroy);
expectedCallState.changeStartCalls++;
expectedCallState.createViewCalls++;
assertCalls(expectedCallState, controller);
container.addView(to);
ViewUtils.setAttached(to, true);
assertCalls(changeStart + 1, changeEnd, bindView + 1, attach + 1, unbindView, detach, destroy);
expectedCallState.attachCalls++;
assertCalls(expectedCallState, controller);
changeListener.onChangeCompleted();
expectedCallState.changeEndCalls++;
assertCalls(expectedCallState, controller);
}
});
}
private ChangeHandler getPopHandler(final int changeStart, final int changeEnd, final int bindView, final int attach, final int unbindView, final int detach, final int destroy) {
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) {
assertCalls(changeStart + 1, changeEnd, bindView, attach, unbindView, detach, destroy);
expectedCallState.changeStartCalls++;
assertCalls(expectedCallState, controller);
container.removeView(from);
ViewUtils.setAttached(from, false);
assertCalls(changeStart + 1, changeEnd, bindView, attach, unbindView + 1, detach + 1, destroy + 1);
expectedCallState.destroyViewCalls++;
expectedCallState.detachCalls++;
expectedCallState.destroyCalls++;
assertCalls(expectedCallState, controller);
changeListener.onChangeCompleted();
expectedCallState.changeEndCalls++;
assertCalls(expectedCallState, controller);
}
});
}
private void assertCalls(int changeStart, int changeEnd, int bindView, int attach, int unbindView, int detach, int destroy) {
Assert.assertEquals(changeStart, mChangeStartCalls);
Assert.assertEquals(changeEnd, mChangeEndCalls);
Assert.assertEquals(bindView, mCreateViewCalls);
Assert.assertEquals(attach, mAttachCalls);
Assert.assertEquals(unbindView, mDestroyViewCalls);
Assert.assertEquals(detach, mDetachCalls);
Assert.assertEquals(destroy, mDestroyCalls);
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) {
mChangeStartCalls++;
mCurrentCallState.changeStartCalls++;
}
@Override
public void onChangeEnd(@NonNull Controller controller, @NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
mChangeEndCalls++;
mCurrentCallState.changeEndCalls++;
}
@Override
public void postCreateView(@NonNull Controller controller, @NonNull View view) {
mCreateViewCalls++;
mCurrentCallState.createViewCalls++;
}
@Override
public void postAttach(@NonNull Controller controller, @NonNull View view) {
mAttachCalls++;
mCurrentCallState.attachCalls++;
}
@Override
public void postDestroyView(@NonNull Controller controller) {
mDestroyViewCalls++;
mCurrentCallState.destroyViewCalls++;
}
@Override
public void postDetach(@NonNull Controller controller, @NonNull View view) {
mDetachCalls++;
mCurrentCallState.detachCalls++;
}
@Override
public void postDestroy(@NonNull Controller controller) {
mDestroyCalls++;
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++;
}
});
}
@@ -293,4 +431,5 @@ public class ControllerTests {
mListener.performChange(container, from, to, isPush, changeListener);
}
}
}
@@ -3,4 +3,12 @@ package com.bluelinelabs.conductor;
import android.app.Activity;
public class TestActivity extends Activity {
public boolean isChangingConfigurations = false;
@Override
public boolean isChangingConfigurations() {
return isChangingConfigurations;
}
}
@@ -1,5 +1,6 @@
package com.bluelinelabs.conductor;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
@@ -7,18 +8,92 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
public class TestController extends Controller {
@IdRes public static final int VIEW_ID = 2342;
public TestController() { }
private static final String KEY_CALL_STATE = "TestController.currentCallState";
public CallState currentCallState;
public TestController() {
currentCallState = new CallState();
}
@NonNull
@Override
protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
currentCallState.createViewCalls++;
View view = new FrameLayout(inflater.getContext());
view.setId(VIEW_ID);
return view;
}
@Override
protected void onChangeStarted(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
super.onChangeStarted(changeHandler, changeType);
currentCallState.changeStartCalls++;
}
@Override
protected void onChangeEnded(@NonNull ControllerChangeHandler changeHandler, @NonNull ControllerChangeType changeType) {
super.onChangeEnded(changeHandler, changeType);
currentCallState.changeEndCalls++;
}
@Override
protected void onAttach(@NonNull View view) {
super.onAttach(view);
currentCallState.attachCalls++;
}
@Override
protected void onDetach(@NonNull View view) {
super.onDetach(view);
currentCallState.detachCalls++;
}
@Override
protected void onDestroyView(View view) {
super.onDestroyView(view);
currentCallState.destroyViewCalls++;
}
@Override
protected void onDestroy() {
super.onDestroy();
currentCallState.destroyCalls++;
}
@Override
protected void onSaveViewState(@NonNull View view, @NonNull Bundle outState) {
super.onSaveViewState(view, outState);
currentCallState.saveViewStateCalls++;
}
@Override
protected void onRestoreViewState(@NonNull View view, @NonNull Bundle savedViewState) {
super.onRestoreViewState(view, savedViewState);
currentCallState.restoreViewStateCalls++;
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
currentCallState.saveInstanceStateCalls++;
outState.putParcelable(KEY_CALL_STATE, currentCallState);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
currentCallState = savedInstanceState.getParcelable(KEY_CALL_STATE);
currentCallState.restoreInstanceStateCalls++;
}
}
@@ -16,10 +16,10 @@
<ImageView
android:id="@+id/image_view"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_width="@dimen/display_target_image_size"
android:layout_height="@dimen/display_target_image_size"
android:layout_gravity="center_horizontal"
android:layout_margin="24dp"
android:layout_margin="@dimen/display_target_image_margin"
/>
<LinearLayout
+8
View File
@@ -0,0 +1,8 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">24dp</dimen>
<dimen name="activity_vertical_margin">24dp</dimen>
<dimen name="display_target_image_size">120dp</dimen>
<dimen name="display_target_image_margin">16dp</dimen>
</resources>
+3
View File
@@ -2,4 +2,7 @@
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="display_target_image_size">200dp</dimen>
<dimen name="display_target_image_margin">24dp</dimen>
</resources>
+1 -1
View File
@@ -5,7 +5,7 @@ ext {
buildToolsVersion = '23.0.2'
versionCode = 1
versionName = '1.1.3'
versionName = '1.1.4'
publishedVersionName = '1.1.3'
supportV4 = 'com.android.support:support-v4:23.1.1'