From a967094979ec5cd1984b1a322e5ba0b05c94679a Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Fri, 15 Jan 2016 23:18:59 +1100 Subject: [PATCH 01/10] Add abstract stateful manager --- build.gradle | 4 +- .../internal/BaseControllerImpl.java | 7 +- .../mvc/manager/AbstractStatefulManager.java | 103 +++++++++++++ .../mvc/manager/TestStatefulManager.java | 144 ++++++++++++++++++ 4 files changed, 253 insertions(+), 5 deletions(-) create mode 100644 library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java create mode 100644 library/android-mvc-controller/src/test/java/com/shipdream/lib/android/mvc/manager/TestStatefulManager.java diff --git a/build.gradle b/build.gradle index a501e40..b5e2b9a 100644 --- a/build.gradle +++ b/build.gradle @@ -73,8 +73,8 @@ ext { gitUrl = 'https://github.com/kejunxia/AndroidMvc.git' // Git repository URL version = [ major: 1, - minor: 5, - patch : 3 + minor: 6, + patch : 0 ] libGroup = 'com.shipdream' libVersion = "${version.major}.${version.minor}.${version.patch}" diff --git a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/controller/internal/BaseControllerImpl.java b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/controller/internal/BaseControllerImpl.java index 73fa61f..4bf548a 100644 --- a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/controller/internal/BaseControllerImpl.java +++ b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/controller/internal/BaseControllerImpl.java @@ -75,13 +75,14 @@ public void onConstruct() { } private MODEL createModelInstance() { - if (getModelClassType() == null) { + Class type = getStateType(); + if (type == null) { return null; } else { try { - return new ReflectUtils.newObjectByType<>(getModelClassType()).newInstance(); + return new ReflectUtils.newObjectByType<>(type).newInstance(); } catch (Exception e) { - throw new RuntimeException("Fail to instantiate model by its default constructor"); + throw new RuntimeException("Fail to instantiate state by its default constructor"); } } } diff --git a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java new file mode 100644 index 0000000..7ec3280 --- /dev/null +++ b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java @@ -0,0 +1,103 @@ +package com.shipdream.lib.android.mvc.manager; + +import com.shipdream.lib.android.mvc.Constructable; +import com.shipdream.lib.android.mvc.Disposable; +import com.shipdream.lib.android.mvc.StateKeeper; +import com.shipdream.lib.android.mvc.StateManaged; +import com.shipdream.lib.poke.util.ReflectUtils; + +/** + * Abstract manager with state that needs to be managed. + */ +public abstract class AbstractStatefulManager implements StateManaged, + Constructable, Disposable { + private STATE state; + + public void bindState(STATE state) { + if (state == null) { + throw new IllegalArgumentException("Can't bind a null state to a manage explicitly."); + } + this.state = state; + } + + /** + * Called when the controller is constructed. Note that it could be called either when the + * controller is instantiated for the first time or restored by views. + * + *

The model of the controller will be instantiated by model's default no-argument constructor. + * However, if the controller needs to be restored, a new instance of model restored by + * {@link #restoreState(Object)} will replace the model created here.

+ */ + public void onConstruct() { + state = createModelInstance(); + } + + private STATE createModelInstance() { + Class type = getStateType(); + if (type == null) { + return null; + } else { + try { + return new ReflectUtils.newObjectByType<>(type).newInstance(); + } catch (Exception e) { + throw new RuntimeException("Fail to instantiate state by its default constructor"); + } + } + } + + /** + * Called when the controller is disposed. This occurs when the controller is de-referenced and + * not retained by any objects. + */ + @Override + public void onDisposed() { + } + + /** + * Method of {@link StateManaged} that allows {@link StateKeeper} to save and get the state of + * which is also the model the controller. + * + * @return Null if the controller doesn't need to get its state saved and restored + * automatically. e.g. The controller always loads resource from remote services so that + * its state can be thought persisted by the remote services. Otherwise the model of the controller + */ + @Override + final public STATE getState() { + return state; + } + + /** + * Method of {@link StateManaged} that allows {@link StateKeeper} to save and get the state of + * which is also the model the controller. + * + * @return The class type of the model of the controller + */ + @Override + abstract public Class getStateType(); + + /** + * Method of {@link StateManaged} that allows {@link StateKeeper} to save and get the state of + * which is also the model the controller. + *

+ * Note that if the controller doesn't need its state saved and restored automatically return + * null in {@link #getStateType()} and then this method will have no effect. + *

+ * + * @param restoredState The restored state by {@link StateKeeper} that will be bound to the + * controller on the view referencing the controller is restored. + */ + @Override + final public void restoreState(STATE restoredState) { + if (getStateType() != null) { + bindState(restoredState); + } + onRestored(); + } + + /** + * Called when the controller is restored after {@link #restoreState(Object)} is called. + */ + public void onRestored() { + } + +} diff --git a/library/android-mvc-controller/src/test/java/com/shipdream/lib/android/mvc/manager/TestStatefulManager.java b/library/android-mvc-controller/src/test/java/com/shipdream/lib/android/mvc/manager/TestStatefulManager.java new file mode 100644 index 0000000..8bbdcd7 --- /dev/null +++ b/library/android-mvc-controller/src/test/java/com/shipdream/lib/android/mvc/manager/TestStatefulManager.java @@ -0,0 +1,144 @@ +package com.shipdream.lib.android.mvc.manager; + +import org.junit.Assert; +import org.junit.Test; + +public class TestStatefulManager { + @Test(expected = IllegalArgumentException.class) + public void should_throw_exception_when_bind_null_to_stateful_manager() { + AbstractStatefulManager manager = new AbstractStatefulManager() { + @Override + public Class getStateType() { + return String.class; + } + }; + + manager.bindState(null); + } + + @Test + public void should_rebind_state_after_restoring_manager() { + AbstractStatefulManager manager = new AbstractStatefulManager() { + + @Override + public Class getStateType() { + return String.class; + } + }; + + Assert.assertNull(manager.getState()); + + manager.restoreState("A"); + + Assert.assertEquals("A", manager.getState()); + } + + @Test + public void should_call_on_restore_call_back_after_manager_is_restored() { + class MyManager extends AbstractStatefulManager { + private boolean called = false; + + @Override + public Class getStateType() { + return String.class; + } + + @Override + public void onRestored() { + super.onRestored(); + called = true; + } + }; + + MyManager manager = new MyManager(); + + Assert.assertFalse(manager.called); + + manager.restoreState("A"); + + Assert.assertTrue(manager.called); + } + + public void should_create_state_instance_on_construct_when_the_state_type_is_specified_for_a_stateful_manager() { + class MyManager extends AbstractStatefulManager { + @Override + public Class getStateType() { + return String.class; + } + }; + MyManager manager = new MyManager(); + + Assert.assertNull(manager.getState()); + + manager.onConstruct(); + + Assert.assertNotNull(manager.getState()); + } + + public void should_NOT_create_state_instance_on_construct_when_the_state_type_is_null_for_a_stateful_manager() { + class MyManager extends AbstractStatefulManager { + @Override + public Class getStateType() { + return null; + } + }; + MyManager manager = new MyManager(); + + Assert.assertNull(manager.getState()); + + manager.onConstruct(); + + Assert.assertNull(manager.getState()); + } + + @Test(expected = RuntimeException.class) + public void should_throw_excpetion_out_when_creating_state_failed() { + class BadClass { + {int x = 1 / 0;} + } + + class MyManager extends AbstractStatefulManager { + @Override + public Class getStateType() { + return BadClass.class; + } + }; + + MyManager manager = new MyManager(); + + manager.onConstruct(); + } + + @Test(expected = IllegalArgumentException.class) + public void should_throw_excpetion_when_binding_null_to_stateful_manager() { + class MyManager extends AbstractStatefulManager { + @Override + public Class getStateType() { + return String.class; + } + }; + + MyManager manager = new MyManager(); + + manager.bindState(null); + } + + @Test + public void should_be_able_to_successfully_bind_state_to_stateful_manager() { + class MyManager extends AbstractStatefulManager { + @Override + public Class getStateType() { + return String.class; + } + }; + + MyManager manager = new MyManager(); + + Assert.assertNotEquals("B", manager.getState()); + + manager.bindState("B"); + + Assert.assertEquals("B", manager.getState()); + } + +} From fc5ea17124dcc746952c28b94f69da4dfc21b088 Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Fri, 15 Jan 2016 23:22:08 +1100 Subject: [PATCH 02/10] Test abstract stateful manager in UI tests --- .../TestInjectedStateManagedObjects.java | 4 ++-- .../manager/internal/AccountManagerImpl.java | 22 ++++--------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java index 4ed1c04..06b1e24 100644 --- a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java +++ b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java @@ -63,10 +63,10 @@ public void should_manage_state_of_nested_stateManagedObjects() throws Throwable onView(withId(R.id.textA)).check(matches(withText("2:B"))); pressHome(); - waitTest(2000); + waitTest(1000); bringBack(); - waitTest(2000); + waitTest(1000); onView(withId(R.id.fragment_injection_root)).perform(click()); onView(withId(R.id.textA)).check(matches(withText("3:C"))); diff --git a/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/manager/internal/AccountManagerImpl.java b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/manager/internal/AccountManagerImpl.java index 98821fe..490f76f 100644 --- a/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/manager/internal/AccountManagerImpl.java +++ b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/manager/internal/AccountManagerImpl.java @@ -2,20 +2,21 @@ import com.shipdream.lib.android.mvc.Constructable; import com.shipdream.lib.android.mvc.StateManaged; +import com.shipdream.lib.android.mvc.manager.AbstractStatefulManager; import com.shipdream.lib.android.mvc.view.injection.manager.AccountManager; import com.shipdream.lib.android.mvc.view.injection.service.StorageService; import javax.inject.Inject; -public class AccountManagerImpl implements AccountManager, StateManaged, Constructable { - private Session session; +public class AccountManagerImpl extends AbstractStatefulManager + implements AccountManager { @Inject private StorageService storageService; @Override public void setUserId(long id) { - session.setUserId(id); + getState().setUserId(id); } @Override @@ -33,23 +34,8 @@ public void setContent(String content) { storageService.setContent(content); } - @Override - public void onConstruct() { - session = new Session(); - } - @Override public Class getStateType() { return Session.class; } - - @Override - public Session getState() { - return session; - } - - @Override - public void restoreState(Session restoredState) { - this.session = restoredState; - } } From 3e72959b3e325a24c6d3858fbbf6f32428e265e9 Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Fri, 15 Jan 2016 23:39:33 +1100 Subject: [PATCH 03/10] Update documents --- .../internal/BaseControllerImpl.java | 8 ++- .../mvc/manager/AbstractStatefulManager.java | 51 ++++++++++--------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/controller/internal/BaseControllerImpl.java b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/controller/internal/BaseControllerImpl.java index 4bf548a..95b68fb 100644 --- a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/controller/internal/BaseControllerImpl.java +++ b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/controller/internal/BaseControllerImpl.java @@ -98,10 +98,9 @@ public void onDisposed() { } /** + * Model represents the state of view that this controller is managing. * @return @return Null if the controller doesn't need to get its state saved and restored - * automatically when {@link #getModelClassType()} returns null. e.g. The controller - * always loads resource from remote services so that its state can be thought persisted by the - * remote services. Otherwise returns the model of the controller + * automatically when {@link #getModelClassType()} returns null. Otherwise the model. */ @Override public MODEL getModel() { @@ -113,8 +112,7 @@ public MODEL getModel() { * which is also the model the controller. * * @return Null if the controller doesn't need to get its state saved and restored - * automatically. e.g. The controller always loads resource from remote services so that - * its state can be thought persisted by the remote services. Otherwise the model of the controller + * automatically. Otherwise same as {@link #getModel()} */ @Override final public MODEL getState() { diff --git a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java index 7ec3280..8bc30df 100644 --- a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java +++ b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java @@ -7,12 +7,23 @@ import com.shipdream.lib.poke.util.ReflectUtils; /** - * Abstract manager with state that needs to be managed. + * Abstract manager with state that needs to be managed. A stateful manager can be shared by multiple + * controllers. For example, LoginManager is an good example that will manage the state of logged in + * user. The log in user object usually is a part of the state to remember the logged in user. + * + *

+ * Managers should only be serving controllers and not visible to views. + *

*/ public abstract class AbstractStatefulManager implements StateManaged, Constructable, Disposable { private STATE state; + /** + * Bind state to this manager. + * @param state non-null state + * @throws IllegalArgumentException thrown when null is being bound + */ public void bindState(STATE state) { if (state == null) { throw new IllegalArgumentException("Can't bind a null state to a manage explicitly."); @@ -21,12 +32,12 @@ public void bindState(STATE state) { } /** - * Called when the controller is constructed. Note that it could be called either when the - * controller is instantiated for the first time or restored by views. + * Called when the manager is injected for the first time or restored when a new instance of + * this manager needs to be instantiated. * - *

The model of the controller will be instantiated by model's default no-argument constructor. - * However, if the controller needs to be restored, a new instance of model restored by - * {@link #restoreState(Object)} will replace the model created here.

+ *

The model of the manager will be instantiated by model's default no-argument constructor. + * However, if the manager needs to be restored, a new instance of state restored by + * {@link #restoreState(Object)} will replace the state created by this method.

*/ public void onConstruct() { state = createModelInstance(); @@ -46,20 +57,15 @@ private STATE createModelInstance() { } /** - * Called when the controller is disposed. This occurs when the controller is de-referenced and - * not retained by any objects. + * Called when the manager is disposed. This occurs when the manager is de-referenced and + * not retained by any other objects. */ @Override public void onDisposed() { } /** - * Method of {@link StateManaged} that allows {@link StateKeeper} to save and get the state of - * which is also the model the controller. - * - * @return Null if the controller doesn't need to get its state saved and restored - * automatically. e.g. The controller always loads resource from remote services so that - * its state can be thought persisted by the remote services. Otherwise the model of the controller + * @return Null if the manager doesn't need to get its state saved and restored automatically. */ @Override final public STATE getState() { @@ -67,24 +73,21 @@ final public STATE getState() { } /** - * Method of {@link StateManaged} that allows {@link StateKeeper} to save and get the state of - * which is also the model the controller. - * - * @return The class type of the model of the controller + * @return The class type of the state of the controller that will be used by this manager to + * instantiate its state in {@link #onConstruct()} */ @Override abstract public Class getStateType(); /** - * Method of {@link StateManaged} that allows {@link StateKeeper} to save and get the state of - * which is also the model the controller. + * Restore the state of the manager. *

- * Note that if the controller doesn't need its state saved and restored automatically return - * null in {@link #getStateType()} and then this method will have no effect. + * Note that if the manager doesn't need its state saved and restored automatically and return + * null in {@link #getStateType()}, then this method will have no effect. *

* * @param restoredState The restored state by {@link StateKeeper} that will be bound to the - * controller on the view referencing the controller is restored. + * manager when the views of app are restored. */ @Override final public void restoreState(STATE restoredState) { @@ -95,7 +98,7 @@ final public void restoreState(STATE restoredState) { } /** - * Called when the controller is restored after {@link #restoreState(Object)} is called. + * Called when the manager is restored after {@link #restoreState(Object)} is called. */ public void onRestored() { } From 50a27687984547679e2aa2a895403e479dc26a46 Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Sun, 17 Jan 2016 11:10:41 +1100 Subject: [PATCH 04/10] Add ui test to ensure rootFragment calls onViewReady after all stateManaged object are restored when app restores --- ...tInjectionAndLifeCycleForRootFragment.java | 69 +++++++++++++++++ .../src/main/AndroidManifest.xml | 3 + ...InjectionTestActivityTestRootFragment.java | 77 +++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java create mode 100644 library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/InjectionTestActivityTestRootFragment.java diff --git a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java new file mode 100644 index 0000000..97090c4 --- /dev/null +++ b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java @@ -0,0 +1,69 @@ +/* + * Copyright 2015 Kejun Xia + * + * 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. + */ + +package com.shipdream.lib.android.mvc.view.injection; + +import android.util.Log; + +import com.shipdream.lib.android.mvc.view.BaseTestCase; +import com.shipdream.lib.android.mvc.view.test.R; + +import org.junit.Test; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +public class TestInjectionAndLifeCycleForRootFragment extends BaseTestCase { + + @Override + protected void waitTest() throws InterruptedException { + waitTest(1000); + } + + public TestInjectionAndLifeCycleForRootFragment() { + super(InjectionTestActivityTestRootFragment.class); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + waitTest(); + } + + @Test + public void test_should_delay_call_on_view_ready_on_root_fragment_after_dependencies_injected_when_restore_from_kill() throws Throwable { + if (!isDontKeepActivities()) { + Log.i(getClass().getSimpleName(), "Not tested as Don't Keep Activities setting is disabled"); + return; + } + + //=============================> At A + onView(withId(R.id.textA)).check(matches(withText("Added by FragmentA"))); + onView(withId(R.id.textB)).check(matches(withText("Added by FragmentA"))); + onView(withId(R.id.textC)).check(matches(withText(""))); + + pressHome(); + waitTest(); + + bringBack(); + waitTest(); + onView(withId(R.id.textA)).check(matches(withText("Added by FragmentA\nOK"))); + onView(withId(R.id.textB)).check(matches(withText("Added by FragmentA"))); + } + +} diff --git a/library/android-mvc-test/src/main/AndroidManifest.xml b/library/android-mvc-test/src/main/AndroidManifest.xml index ae10a4d..07790e1 100644 --- a/library/android-mvc-test/src/main/AndroidManifest.xml +++ b/library/android-mvc-test/src/main/AndroidManifest.xml @@ -50,6 +50,9 @@ android:theme="@style/Theme.AppCompat.Light.NoActionBar"> + + diff --git a/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/InjectionTestActivityTestRootFragment.java b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/InjectionTestActivityTestRootFragment.java new file mode 100644 index 0000000..8af2458 --- /dev/null +++ b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/InjectionTestActivityTestRootFragment.java @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Kejun Xia + * + * 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. + */ + +package com.shipdream.lib.android.mvc.view.injection; + +import android.os.Bundle; +import android.view.View; + +import com.shipdream.lib.android.mvc.controller.NavigationController; +import com.shipdream.lib.android.mvc.view.MvcActivity; +import com.shipdream.lib.android.mvc.view.MvcFragment; +import com.shipdream.lib.android.mvc.view.injection.controller.ControllerA; +import com.shipdream.lib.android.mvc.view.nav.MvcTestActivityNavigation; + +import javax.inject.Inject; + +public class InjectionTestActivityTestRootFragment extends MvcActivity { + @Override + protected Class mapNavigationFragment(String locationId) { + switch (locationId) { + case MvcTestActivityNavigation.Loc.A: + return FragmentA.class; + default: + return null; + } + } + + @Override + protected Class getDelegateFragmentClass() { + return HomeFragment.class; + } + + public static class HomeFragment extends DelegateFragment { + @Inject + private NavigationController navigationController; + + @Inject + private ControllerA controllerA; + + @Override + protected void onStartUp() { + navigationController.navigate(this).to(MvcTestActivityNavigation.Loc.A, null); + } + + @Override + public void onViewReady(View view, Bundle savedInstanceState, Reason reason) { + super.onViewReady(view, savedInstanceState, reason); + + if (savedInstanceState != null) { + controllerA.addTag("OK"); + } + } + + @Override + public void onViewStateRestored(Bundle savedInstanceState) { + super.onViewStateRestored(savedInstanceState); + + if (savedInstanceState != null) { + System.out.print(""); + } + } + } + +} From d988169d2b80934abe17875aadb2317d94453102 Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Sun, 17 Jan 2016 18:48:28 +1100 Subject: [PATCH 05/10] Log proper info of event posting failures --- .../lib/android/mvc/event/bus/internal/EventBusImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/event/bus/internal/EventBusImpl.java b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/event/bus/internal/EventBusImpl.java index cba7e9f..d2b882e 100644 --- a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/event/bus/internal/EventBusImpl.java +++ b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/event/bus/internal/EventBusImpl.java @@ -109,8 +109,12 @@ public void post(Object event) { } catch (IllegalAccessException e) { logger.warn(e.getMessage(), e); } catch (InvocationTargetException e) { + String msg = e.getMessage(); + if (msg == null || msg.isEmpty() && e.getCause() != null) { + msg = e.getCause().getMessage(); + } throw new RuntimeException("Not able to post event - " - + event.getClass().getName() + " due to error: " + e.getMessage(), e); + + event.getClass().getName() + " due to error: " + msg, e.getCause()); } } } From abe65b7383e7f59423a3c4991f22d0edeb245151 Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Sun, 17 Jan 2016 22:45:19 +1100 Subject: [PATCH 06/10] Let fragments release themselves --- .../TestInjectedStateManagedObjects.java | 2 +- .../viewpager/TestFragmentsInViewPager.java | 6 ++-- .../res/layout/fragment_view_pager_home.xml | 7 +++++ .../lib/android/mvc/view/MvcActivity.java | 31 ++++++++----------- .../lib/android/mvc/view/MvcFragment.java | 16 +++------- 5 files changed, 28 insertions(+), 34 deletions(-) diff --git a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java index 06b1e24..38c5e45 100644 --- a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java +++ b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java @@ -43,7 +43,7 @@ public void tearDown() throws Exception { } @Test - public void should_manage_state_of_nested_stateManagedObjects() throws Throwable { + public void test_should_manage_state_of_nested_stateManagedObjects() throws Throwable { if (!isDontKeepActivities()) { Log.i(getClass().getSimpleName(), "testLifeCyclesWhenKeepActivities not tested as Don't Keep Activities setting is disabled"); return; diff --git a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/viewpager/TestFragmentsInViewPager.java b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/viewpager/TestFragmentsInViewPager.java index 7fa268d..44a9836 100644 --- a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/viewpager/TestFragmentsInViewPager.java +++ b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/viewpager/TestFragmentsInViewPager.java @@ -156,7 +156,7 @@ public void test_should_call_onViewReady_in_tab_fragments_when_restored_hosting_ lifeCycleValidatorC.expect(); //=============================> At Sub Fragment - navigationController.navigateTo(this, SubFragment.class.getSimpleName()); + navigationController.navigate(this).to(SubFragment.class.getSimpleName()); waitTest(1200); lifeCycleValidator.expect(LifeCycle.onPushingToBackStack, LifeCycle.onDestroyView); @@ -183,8 +183,8 @@ public void test_should_call_onViewReady_in_tab_fragments_when_restored_hosting_ lifeCycleValidatorC.expect(); - //=============================> At A - navigationController.navigateBack(this); + //=============================> Back to home + navigationController.navigate(this).back(); waitTest(1200); lifeCycleValidator.expect( diff --git a/library/android-mvc-test/src/main/res/layout/fragment_view_pager_home.xml b/library/android-mvc-test/src/main/res/layout/fragment_view_pager_home.xml index 9bb020c..d0dd5bd 100644 --- a/library/android-mvc-test/src/main/res/layout/fragment_view_pager_home.xml +++ b/library/android-mvc-test/src/main/res/layout/fragment_view_pager_home.xml @@ -20,6 +20,13 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> + + + Date: Sun, 17 Jan 2016 23:03:00 +1100 Subject: [PATCH 07/10] Delegate fragment will call onViewReady after all lost state are restored --- ...tInjectionAndLifeCycleForRootFragment.java | 2 +- .../lib/android/mvc/view/MvcActivity.java | 21 ++++++------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java index 97090c4..33513fe 100644 --- a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java +++ b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java @@ -62,7 +62,7 @@ public void test_should_delay_call_on_view_ready_on_root_fragment_after_dependen bringBack(); waitTest(); - onView(withId(R.id.textA)).check(matches(withText("Added by FragmentA\nOK"))); + onView(withId(R.id.textA)).check(matches(withText("Added by FragmentA\nOK\nAdded by FragmentA"))); onView(withId(R.id.textB)).check(matches(withText("Added by FragmentA"))); } diff --git a/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcActivity.java b/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcActivity.java index c479c9d..92de926 100644 --- a/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcActivity.java +++ b/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcActivity.java @@ -348,19 +348,14 @@ public void onCreate(Bundle savedInstanceState) { setHasOptionsMenu(true); MvcActivity activity = ((MvcActivity) getActivity()); activity.delegateFragment = this; - -// if (savedInstanceState != null) { -// //restoring, ensure this root fragment wait state restored before onViewReady is called -// isStateManagedByRootDelegateFragment = true; -// } } -// public void onViewCreated(final View view, final Bundle savedInstanceState) { -// if (savedInstanceState != null) { -// notifyAllSubMvcFragmentsTheirStateIsManagedByMe(this, true); -// } -// super.onViewCreated(view, savedInstanceState); -// } + public void onViewCreated(final View view, final Bundle savedInstanceState) { + if (savedInstanceState != null) { + notifyAllSubMvcFragmentsTheirStateIsManagedByMe(this, true); + } + super.onViewCreated(view, savedInstanceState); + } private boolean firstTimeRun = false; @@ -371,10 +366,6 @@ public void onViewReady(View view, Bundle savedInstanceState, Reason reason) { if (reason.isFirstTime()) { firstTimeRun = true; } - - if (savedInstanceState != null) { - notifyAllSubMvcFragmentsTheirStateIsManagedByMe(this, true); - } } @Override From bf9fe4688a6765169fa04df58b88211d7a6e8e4b Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Sun, 17 Jan 2016 23:13:26 +1100 Subject: [PATCH 08/10] Hide onViewCreated of MvcFragment --- .../TestInjectionAndLifeCycleForRootFragment.java | 2 +- .../shipdream/lib/android/mvc/view/MvcActivity.java | 3 +-- .../shipdream/lib/android/mvc/view/MvcFragment.java | 10 +++++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java index 33513fe..800b3e4 100644 --- a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java +++ b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectionAndLifeCycleForRootFragment.java @@ -63,7 +63,7 @@ public void test_should_delay_call_on_view_ready_on_root_fragment_after_dependen bringBack(); waitTest(); onView(withId(R.id.textA)).check(matches(withText("Added by FragmentA\nOK\nAdded by FragmentA"))); - onView(withId(R.id.textB)).check(matches(withText("Added by FragmentA"))); + onView(withId(R.id.textB)).check(matches(withText("Added by FragmentA\nAdded by FragmentA"))); } } diff --git a/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcActivity.java b/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcActivity.java index 92de926..277c2ba 100644 --- a/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcActivity.java +++ b/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcActivity.java @@ -350,11 +350,10 @@ public void onCreate(Bundle savedInstanceState) { activity.delegateFragment = this; } - public void onViewCreated(final View view, final Bundle savedInstanceState) { + void onPreViewReady(final View view, final Bundle savedInstanceState) { if (savedInstanceState != null) { notifyAllSubMvcFragmentsTheirStateIsManagedByMe(this, true); } - super.onViewCreated(view, savedInstanceState); } private boolean firstTimeRun = false; diff --git a/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcFragment.java b/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcFragment.java index 7db722f..5b1f0e1 100644 --- a/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcFragment.java +++ b/library/android-mvc/src/main/java/com/shipdream/lib/android/mvc/view/MvcFragment.java @@ -232,6 +232,12 @@ final public View onCreateView(LayoutInflater inflater, ViewGroup container, Bun return inflater.inflate(getLayoutResId(), container, false); } + /** + * Called when view is created by before {@link #onViewReady(View, Bundle, Reason)} is called + */ + void onPreViewReady(View view, Bundle savedInstanceState) { + } + /** * This Android lifecycle callback is sealed. Use {@link #onViewReady(View, Bundle, Reason)} * instead which provides a flag to indicate if the creation of the view is caused by rotation. @@ -241,10 +247,12 @@ final public View onCreateView(LayoutInflater inflater, ViewGroup container, Bun * otherwise the state to restore and recreate the view */ @Override - public void onViewCreated(final View view, final Bundle savedInstanceState) { + final public void onViewCreated(final View view, final Bundle savedInstanceState) { fragmentComesBackFromBackground = false; eventRegister.registerEventBuses(); + onPreViewReady(view, savedInstanceState); + final boolean restoring = savedInstanceState != null; if (restoring && isStateManagedByRootDelegateFragment) { ((MvcActivity)getActivity()).addPendingOnViewReadyActions(new Runnable() { From fe322079e74f32b0f4b4991ba3be97a4a2998b38 Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Sun, 17 Jan 2016 23:29:28 +1100 Subject: [PATCH 09/10] Fix ui tests failure duo to activity race conditions --- .../TestInjectedStateManagedObjects.java | 8 +-- .../viewpager/TestFragmentsInViewPager.java | 4 ++ .../src/main/AndroidManifest.xml | 3 ++ ...ectionTestActivityStateManagedObjects.java | 52 +++++++++++++++++++ .../mvc/view/viewpager/BaseTabFragment.java | 2 +- 5 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/InjectionTestActivityStateManagedObjects.java diff --git a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java index 38c5e45..9b60805 100644 --- a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java +++ b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/injection/TestInjectedStateManagedObjects.java @@ -19,7 +19,6 @@ import android.util.Log; import com.shipdream.lib.android.mvc.view.BaseTestCase; -import com.shipdream.lib.android.mvc.view.nav.MvcTestActivityNavigation; import com.shipdream.lib.android.mvc.view.test.R; import org.junit.Test; @@ -30,10 +29,10 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; -public class TestInjectedStateManagedObjects extends BaseTestCase { +public class TestInjectedStateManagedObjects extends BaseTestCase { public TestInjectedStateManagedObjects() { - super(InjectionTestActivity.class); + super(InjectionTestActivityStateManagedObjects.class); } @Override @@ -49,9 +48,6 @@ public void test_should_manage_state_of_nested_stateManagedObjects() throws Thro return; } - navigationController.navigate(this).to(MvcTestActivityNavigation.Loc.D); - waitTest(); - onView(withId(R.id.textA)).check(matches(withText(""))); onView(withId(R.id.fragment_injection_root)).perform(click()); diff --git a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/viewpager/TestFragmentsInViewPager.java b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/viewpager/TestFragmentsInViewPager.java index 44a9836..47ea1a5 100644 --- a/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/viewpager/TestFragmentsInViewPager.java +++ b/library/android-mvc-test/src/androidTest/java/com/shipdream/lib/android/mvc/view/viewpager/TestFragmentsInViewPager.java @@ -212,6 +212,10 @@ public void test_should_call_onViewReady_in_tab_fragments_when_restored_hosting_ LifeCycle.onPoppedOutToFront); lifeCycleValidatorC.expect(); + + navigationController.navigate(this).back(null); + navigationController.navigate(this).back(); + waitTest(1000); } @Test diff --git a/library/android-mvc-test/src/main/AndroidManifest.xml b/library/android-mvc-test/src/main/AndroidManifest.xml index 07790e1..ac2e652 100644 --- a/library/android-mvc-test/src/main/AndroidManifest.xml +++ b/library/android-mvc-test/src/main/AndroidManifest.xml @@ -50,6 +50,9 @@ android:theme="@style/Theme.AppCompat.Light.NoActionBar"> + + diff --git a/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/InjectionTestActivityStateManagedObjects.java b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/InjectionTestActivityStateManagedObjects.java new file mode 100644 index 0000000..65368fa --- /dev/null +++ b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/InjectionTestActivityStateManagedObjects.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015 Kejun Xia + * + * 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. + */ + +package com.shipdream.lib.android.mvc.view.injection; + +import com.shipdream.lib.android.mvc.controller.NavigationController; +import com.shipdream.lib.android.mvc.view.MvcActivity; +import com.shipdream.lib.android.mvc.view.MvcFragment; +import com.shipdream.lib.android.mvc.view.nav.MvcTestActivityNavigation; + +import javax.inject.Inject; + +public class InjectionTestActivityStateManagedObjects extends MvcActivity { + @Override + protected Class mapNavigationFragment(String locationId) { + switch (locationId) { + case MvcTestActivityNavigation.Loc.D: + return FragmentD.class; + default: + return null; + } + } + + @Override + protected Class getDelegateFragmentClass() { + return HomeFragment.class; + } + + public static class HomeFragment extends DelegateFragment { + @Inject + private NavigationController navigationController; + + @Override + protected void onStartUp() { + navigationController.navigate(this).to(MvcTestActivityNavigation.Loc.D, null); + } + } + +} diff --git a/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/viewpager/BaseTabFragment.java b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/viewpager/BaseTabFragment.java index 228f95b..ed6122b 100644 --- a/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/viewpager/BaseTabFragment.java +++ b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/viewpager/BaseTabFragment.java @@ -8,7 +8,7 @@ public abstract class BaseTabFragment extends MvcFragment { protected abstract LifeCycleMonitor getLifeCycleMonitor(); - + @Override public void onViewReady(View view, Bundle savedInstanceState, MvcFragment.Reason reason) { getLifeCycleMonitor().onCreateView(view, savedInstanceState); From 0f1540a60eaf4e268ba3801950c52f09a0c8f59f Mon Sep 17 00:00:00 2001 From: Kejun Xia Date: Mon, 18 Jan 2016 18:53:25 +1100 Subject: [PATCH 10/10] Prepare release 1.6.0 --- ChangeLog.md | 4 ++++ ...StatefulManager.java => BaseManagerImpl.java} | 2 +- .../android/mvc/manager/TestStatefulManager.java | 16 ++++++++-------- .../manager/internal/AccountManagerImpl.java | 6 ++---- 4 files changed, 15 insertions(+), 13 deletions(-) rename library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/{AbstractStatefulManager.java => BaseManagerImpl.java} (97%) diff --git a/ChangeLog.md b/ChangeLog.md index b48915c..d1a987c 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,7 @@ +Version:1.6.0 +* Add BaseManagerImpl. Logic and data shared by multiple controllers can be put into managers and injected into controllers. +* Delegate fragment's onViewReady lifecycle will be called after state of all controllers are restored if activity is killed by OS + Version:1.5.3 * MvcGraph able to inject concrete class with a public constructor * Fix bug that sub fragments' controller do not restore state diff --git a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/BaseManagerImpl.java similarity index 97% rename from library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java rename to library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/BaseManagerImpl.java index 8bc30df..aece31f 100644 --- a/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/AbstractStatefulManager.java +++ b/library/android-mvc-controller/src/main/java/com/shipdream/lib/android/mvc/manager/BaseManagerImpl.java @@ -15,7 +15,7 @@ * Managers should only be serving controllers and not visible to views. *

*/ -public abstract class AbstractStatefulManager implements StateManaged, +public abstract class BaseManagerImpl implements StateManaged, Constructable, Disposable { private STATE state; diff --git a/library/android-mvc-controller/src/test/java/com/shipdream/lib/android/mvc/manager/TestStatefulManager.java b/library/android-mvc-controller/src/test/java/com/shipdream/lib/android/mvc/manager/TestStatefulManager.java index 8bbdcd7..3816e5e 100644 --- a/library/android-mvc-controller/src/test/java/com/shipdream/lib/android/mvc/manager/TestStatefulManager.java +++ b/library/android-mvc-controller/src/test/java/com/shipdream/lib/android/mvc/manager/TestStatefulManager.java @@ -6,7 +6,7 @@ public class TestStatefulManager { @Test(expected = IllegalArgumentException.class) public void should_throw_exception_when_bind_null_to_stateful_manager() { - AbstractStatefulManager manager = new AbstractStatefulManager() { + BaseManagerImpl manager = new BaseManagerImpl() { @Override public Class getStateType() { return String.class; @@ -18,7 +18,7 @@ public Class getStateType() { @Test public void should_rebind_state_after_restoring_manager() { - AbstractStatefulManager manager = new AbstractStatefulManager() { + BaseManagerImpl manager = new BaseManagerImpl() { @Override public Class getStateType() { @@ -35,7 +35,7 @@ public Class getStateType() { @Test public void should_call_on_restore_call_back_after_manager_is_restored() { - class MyManager extends AbstractStatefulManager { + class MyManager extends BaseManagerImpl { private boolean called = false; @Override @@ -60,7 +60,7 @@ public void onRestored() { } public void should_create_state_instance_on_construct_when_the_state_type_is_specified_for_a_stateful_manager() { - class MyManager extends AbstractStatefulManager { + class MyManager extends BaseManagerImpl { @Override public Class getStateType() { return String.class; @@ -76,7 +76,7 @@ public Class getStateType() { } public void should_NOT_create_state_instance_on_construct_when_the_state_type_is_null_for_a_stateful_manager() { - class MyManager extends AbstractStatefulManager { + class MyManager extends BaseManagerImpl { @Override public Class getStateType() { return null; @@ -97,7 +97,7 @@ class BadClass { {int x = 1 / 0;} } - class MyManager extends AbstractStatefulManager { + class MyManager extends BaseManagerImpl { @Override public Class getStateType() { return BadClass.class; @@ -111,7 +111,7 @@ public Class getStateType() { @Test(expected = IllegalArgumentException.class) public void should_throw_excpetion_when_binding_null_to_stateful_manager() { - class MyManager extends AbstractStatefulManager { + class MyManager extends BaseManagerImpl { @Override public Class getStateType() { return String.class; @@ -125,7 +125,7 @@ public Class getStateType() { @Test public void should_be_able_to_successfully_bind_state_to_stateful_manager() { - class MyManager extends AbstractStatefulManager { + class MyManager extends BaseManagerImpl { @Override public Class getStateType() { return String.class; diff --git a/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/manager/internal/AccountManagerImpl.java b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/manager/internal/AccountManagerImpl.java index 490f76f..eeff482 100644 --- a/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/manager/internal/AccountManagerImpl.java +++ b/library/android-mvc-test/src/main/java/com/shipdream/lib/android/mvc/view/injection/manager/internal/AccountManagerImpl.java @@ -1,14 +1,12 @@ package com.shipdream.lib.android.mvc.view.injection.manager.internal; -import com.shipdream.lib.android.mvc.Constructable; -import com.shipdream.lib.android.mvc.StateManaged; -import com.shipdream.lib.android.mvc.manager.AbstractStatefulManager; +import com.shipdream.lib.android.mvc.manager.BaseManagerImpl; import com.shipdream.lib.android.mvc.view.injection.manager.AccountManager; import com.shipdream.lib.android.mvc.view.injection.service.StorageService; import javax.inject.Inject; -public class AccountManagerImpl extends AbstractStatefulManager +public class AccountManagerImpl extends BaseManagerImpl implements AccountManager { @Inject