Skip to content

Commit 7e00b37

Browse files
author
Daniel Novak
committed
Remove onRetainNonConfigurationInstance
1 parent 6887cc1 commit 7e00b37

File tree

8 files changed

+112
-64
lines changed

8 files changed

+112
-64
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
1818
# org.gradle.parallel=true
1919

20-
VERSION_NAME=0.1
20+
VERSION_NAME=0.2

library/src/main/java/eu/inloop/viewmodel/IViewModelProvider.java

Lines changed: 0 additions & 14 deletions
This file was deleted.

library/src/main/java/eu/inloop/viewmodel/ViewModelHelper.java

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import android.support.annotation.NonNull;
66
import android.support.annotation.Nullable;
77
import android.support.v4.app.Fragment;
8+
import android.support.v4.app.FragmentManager;
89
import android.util.Log;
910

1011
import java.util.UUID;
@@ -14,71 +15,110 @@ public class ViewModelHelper<T extends IView, R extends AbstractViewModel<T>> {
1415
private String mScreenId;
1516
private R mViewModel;
1617
private boolean mModelRemoved;
17-
18-
public void onCreate(@NonNull Activity activity, @Nullable Bundle savedInstanceState,
19-
@NonNull Class<? extends AbstractViewModel<T>> viewModelClass) {
18+
private boolean mOnSaveInstanceCalled;
19+
20+
/**
21+
* Call from {@link android.app.Activity#onCreate(android.os.Bundle)} or
22+
* {@link android.support.v4.app.Fragment#onCreate(android.os.Bundle)}
23+
* @param savedInstanceState
24+
* @param viewModelClass
25+
*/
26+
public void onCreate(@Nullable Bundle savedInstanceState,
27+
@Nullable Class<? extends AbstractViewModel<T>> viewModelClass) {
28+
// no viewmodel for this fragment
2029
if (viewModelClass == null) {
21-
//no viewmodel for this fragment
2230
mViewModel = null;
2331
return;
2432
}
33+
34+
// screen (activity/fragment) created for first time, attach unique ID
2535
if (savedInstanceState == null) {
2636
mScreenId = UUID.randomUUID().toString();
2737
} else {
2838
mScreenId = savedInstanceState.getString("identifier");
39+
mOnSaveInstanceCalled = false;
2940
}
3041

31-
final ViewModelProvider.ViewModelWrapper<T> viewModelWrapper = getViewModelProvider(activity).getViewModelProvider().getViewModel(mScreenId, viewModelClass);
42+
// get model instance for this screen
43+
final ViewModelProvider.ViewModelWrapper<T> viewModelWrapper = ViewModelProvider.getInstance().getViewModel(mScreenId, viewModelClass);
3244
mViewModel = (R) viewModelWrapper.viewModel;
45+
46+
// detect that the system has killed the app - saved instance is not null, but the model was recreated
3347
if (savedInstanceState != null && viewModelWrapper.wasCreated) {
3448
Log.d("model", "Fragment recreated by system - restoring viewmodel");
3549
mViewModel.restoreState(savedInstanceState);
3650
}
3751
}
3852

39-
public void initWithView(T view) {
53+
/**
54+
* Call from {@link android.support.v4.app.Fragment#onViewCreated(android.view.View, android.os.Bundle)}
55+
* or {@link android.app.Activity#onCreate(android.os.Bundle)}
56+
* @param view
57+
*/
58+
public void initWithView(@NonNull T view) {
4059
if (mViewModel == null) {
4160
//no viewmodel for this fragment
4261
return;
4362
}
4463
mViewModel.initWithView(view);
4564
}
4665

66+
/**
67+
* Use in case this model is associated with an {@link android.support.v4.app.Fragment}
68+
* Call from {@link android.support.v4.app.Fragment#onDestroyView()}. Use in case model is associated
69+
* with Fragment
70+
* @param fragment
71+
*/
4772
public void onDestroyView(@NonNull Fragment fragment) {
4873
if (mViewModel == null) {
4974
//no viewmodel for this fragment
5075
return;
5176
}
5277
mViewModel.clearView();
5378
if (fragment.getActivity() != null && fragment.getActivity().isFinishing()) {
54-
removeViewModel(fragment.getActivity());
79+
removeViewModel();
5580
}
5681
}
5782

83+
/**
84+
* Use in case this model is associated with an {@link android.support.v4.app.Fragment}
85+
* Call from {@link android.support.v4.app.Fragment#onDestroy()}
86+
* @param fragment
87+
*/
5888
public void onDestroy(@NonNull Fragment fragment) {
5989
if (mViewModel == null) {
6090
//no viewmodel for this fragment
6191
return;
6292
}
6393
if (fragment.getActivity().isFinishing()) {
64-
removeViewModel(fragment.getActivity());
65-
} else if (fragment.isRemoving()) {
94+
removeViewModel();
95+
} else if (fragment.isRemoving() && !mOnSaveInstanceCalled) {
96+
// The fragment can be still in backstack even if isRemoving() is true.
97+
// We check mOnSaveInstanceCalled - if this was not called then the fragment is totally removed.
6698
Log.d("mode", "Removing viewmodel - fragment replaced");
67-
removeViewModel(fragment.getActivity());
99+
removeViewModel();
68100
}
69101
}
70102

103+
/**
104+
* Use in case this model is associated with an {@link android.app.Activity}
105+
* Call from {@link android.app.Activity#onDestroy()}
106+
* @param activity
107+
*/
71108
public void onDestroy(@NonNull Activity activity) {
72109
if (mViewModel == null) {
73110
//no viewmodel for this fragment
74111
return;
75112
}
76113
mViewModel.clearView();
77114
if (activity.isFinishing()) {
78-
removeViewModel(activity);
115+
removeViewModel();
79116
}
80117
}
81118

119+
/**
120+
* Call from {@link android.app.Activity#onStop()} or {@link android.support.v4.app.Fragment#onStop()}
121+
*/
82122
public void onStop() {
83123
if (mViewModel == null) {
84124
//no viewmodel for this fragment
@@ -87,6 +127,9 @@ public void onStop() {
87127
mViewModel.onStop();
88128
}
89129

130+
/**
131+
* Call from {@link android.app.Activity#onStart()} ()} or {@link android.support.v4.app.Fragment#onStart()} ()}
132+
*/
90133
public void onStart() {
91134
if (mViewModel == null) {
92135
//no viewmodel for this fragment
@@ -95,27 +138,29 @@ public void onStart() {
95138
mViewModel.onStart();
96139
}
97140

141+
142+
@Nullable
98143
public R getViewModel() {
99144
return mViewModel;
100145
}
101146

102-
public void onSaveInstanceState(@Nullable Bundle bundle) {
147+
/**
148+
* Call from {@link android.app.Activity#onSaveInstanceState(android.os.Bundle)}
149+
* or {@link android.support.v4.app.Fragment#onSaveInstanceState(android.os.Bundle)}.
150+
* This allows the model to save its state.
151+
* @param bundle
152+
*/
153+
public void onSaveInstanceState(@NonNull Bundle bundle) {
103154
bundle.putString("identifier", mScreenId);
104155
if (mViewModel != null) {
105156
mViewModel.saveState(bundle);
157+
mOnSaveInstanceCalled = true;
106158
}
107159
}
108160

109-
private IViewModelProvider getViewModelProvider(@NonNull Activity activity) {
110-
if (!(activity instanceof IViewModelProvider)) {
111-
throw new IllegalStateException("Your activity must implement IViewModelProvider");
112-
}
113-
return ((IViewModelProvider)activity);
114-
}
115-
116-
protected boolean removeViewModel(@NonNull Activity activity) {
161+
private boolean removeViewModel() {
117162
if (!mModelRemoved) {
118-
boolean removed = getViewModelProvider(activity).getViewModelProvider().remove(mScreenId);
163+
boolean removed = ViewModelProvider.getInstance().remove(mScreenId);
119164
mViewModel.onModelRemoved();
120165
mModelRemoved = true;
121166
return removed;

library/src/main/java/eu/inloop/viewmodel/ViewModelProvider.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@
1111
*/
1212
public class ViewModelProvider {
1313

14+
private static final ViewModelProvider sInstance = new ViewModelProvider();
15+
1416
private final HashMap<String, AbstractViewModel<? extends IView>> mViewModelCache;
1517

16-
public ViewModelProvider() {
18+
private ViewModelProvider() {
1719
mViewModelCache = new HashMap<>();
1820
}
1921

20-
boolean remove(@NonNull String key) {
22+
public static ViewModelProvider getInstance() {
23+
return sInstance;
24+
}
25+
26+
public boolean remove(@NonNull String key) {
2127
return mViewModelCache.remove(key) != null;
2228
}
2329

library/src/main/java/eu/inloop/viewmodel/base/ViewModelBaseActivity.java

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,50 @@
22

33
import android.os.Bundle;
44
import android.support.v4.app.FragmentActivity;
5-
import android.util.Log;
65

7-
import eu.inloop.viewmodel.IViewModelProvider;
8-
import eu.inloop.viewmodel.ViewModelProvider;
6+
import eu.inloop.viewmodel.AbstractViewModel;
7+
import eu.inloop.viewmodel.IView;
8+
import eu.inloop.viewmodel.ViewModelHelper;
99

10-
public class ViewModelBaseActivity extends FragmentActivity implements IViewModelProvider {
10+
public abstract class ViewModelBaseActivity<T extends IView, R extends AbstractViewModel<T>> extends FragmentActivity implements IView {
1111

12-
private ViewModelProvider mViewModelService;
12+
private ViewModelHelper<T, R> mViewModeHelper = new ViewModelHelper<>();
1313

1414
@Override
1515
protected void onCreate(Bundle savedInstanceState) {
16-
//This code must be execute prior to super.onCreate()
17-
if (getLastCustomNonConfigurationInstance() == null) {
18-
mViewModelService = new ViewModelProvider();
19-
} else {
20-
mViewModelService = (ViewModelProvider) getLastCustomNonConfigurationInstance();
21-
}
2216
super.onCreate(savedInstanceState);
17+
mViewModeHelper.onCreate(savedInstanceState, getViewModelClass());
18+
mViewModeHelper.initWithView((T) this);
2319
}
2420

21+
public abstract Class<R> getViewModelClass();
22+
2523
@Override
26-
public Object onRetainCustomNonConfigurationInstance() {
27-
return mViewModelService;
24+
public void onSaveInstanceState(Bundle outState) {
25+
super.onSaveInstanceState(outState);
26+
mViewModeHelper.onSaveInstanceState(outState);
2827
}
2928

3029
@Override
31-
public ViewModelProvider getViewModelProvider() {
32-
return mViewModelService;
30+
public void onStart() {
31+
super.onStart();
32+
mViewModeHelper.onStart();
3333
}
3434

3535
@Override
36-
protected void onStop() {
37-
if (isFinishing()) {
38-
mViewModelService.removeAllViewModels();
39-
}
36+
public void onStop() {
4037
super.onStop();
38+
mViewModeHelper.onStop();
39+
}
40+
41+
@Override
42+
public void onDestroy() {
43+
mViewModeHelper.onDestroy(this);
44+
super.onDestroy();
45+
}
46+
47+
@SuppressWarnings("unused")
48+
public R getViewModel() {
49+
return mViewModeHelper.getViewModel();
4150
}
4251
}

library/src/main/java/eu/inloop/viewmodel/base/ViewModelBaseFragment.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111

1212
public abstract class ViewModelBaseFragment<T extends IView, R extends AbstractViewModel<T>> extends Fragment {
1313

14-
private ViewModelHelper<T, R> mViewModeHelper = new ViewModelHelper<T, R>();
14+
private ViewModelHelper<T, R> mViewModeHelper = new ViewModelHelper<>();
1515

1616
@Override
1717
public void onCreate(Bundle savedInstanceState) {
1818
super.onCreate(savedInstanceState);
19-
mViewModeHelper.onCreate(getActivity(), savedInstanceState, getViewModelClass());
19+
mViewModeHelper.onCreate(savedInstanceState, getViewModelClass());
2020
}
2121

2222
public abstract Class<R> getViewModelClass();
@@ -57,6 +57,7 @@ public void onDestroy() {
5757
super.onDestroy();
5858
}
5959

60+
@SuppressWarnings("unused")
6061
public R getViewModel() {
6162
return mViewModeHelper.getViewModel();
6263
}

sample/src/main/java/eu/inloop/viewmodel/sample/activity/MainActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ protected void onCreate(Bundle savedInstanceState) {
2424
}
2525
}
2626

27+
@Override
28+
public Class getViewModelClass() {
29+
return null;
30+
}
31+
2732
@OnClick(R.id.button1)
2833
public void onOpenFragmentClicked() {
2934
getSupportFragmentManager().beginTransaction().replace(R.id.root_content, new EmptyFragment(), "empty-fragment").addToBackStack(null).commit();

sample/src/main/java/eu/inloop/viewmodel/sample/activity/ProjectBaseActivity.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
package eu.inloop.viewmodel.sample.activity;
22

33
import android.os.Bundle;
4-
import android.support.v4.app.FragmentActivity;
5-
6-
import eu.inloop.viewmodel.IViewModelProvider;
7-
import eu.inloop.viewmodel.ViewModelProvider;
84
import eu.inloop.viewmodel.base.ViewModelBaseActivity;
95

10-
public class ProjectBaseActivity extends ViewModelBaseActivity {
6+
public abstract class ProjectBaseActivity extends ViewModelBaseActivity {
117

128
@Override
139
protected void onCreate(Bundle savedInstanceState) {

0 commit comments

Comments
 (0)