Skip to content
This repository was archived by the owner on Feb 27, 2025. It is now read-only.

Commit 407cb47

Browse files
committed
Removes WeakReferences and uses lifecycle methods to avoid leaks, except in the TaskItemVM
1 parent 06ecb67 commit 407cb47

File tree

9 files changed

+86
-39
lines changed

9 files changed

+86
-39
lines changed

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskActivity.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class AddEditTaskActivity extends BaseActivity implements AddEditTaskNavi
4040
public static final int ADD_EDIT_RESULT_OK = RESULT_FIRST_USER + 1;
4141

4242
public static final String ADD_EDIT_VIEWMODEL_TAG = "ADD_EDIT_VIEWMODEL_TAG";
43+
private AddEditTaskViewModel mViewModel;
4344

4445
@Override
4546
public boolean onSupportNavigateUp() {
@@ -72,11 +73,18 @@ protected void onCreate(Bundle savedInstanceState) {
7273

7374
AddEditTaskFragment addEditTaskFragment = findOrCreateViewFragment();
7475

75-
AddEditTaskViewModel viewModel = findOrCreateViewModel();
76-
viewModel.setNavigator(this);
76+
mViewModel = findOrCreateViewModel();
7777

7878
// Link View and ViewModel
79-
addEditTaskFragment.setViewModel(viewModel);
79+
addEditTaskFragment.setViewModel(mViewModel);
80+
81+
mViewModel.onActivityCreated(this);
82+
}
83+
84+
@Override
85+
protected void onDestroy() {
86+
mViewModel.onActivityDestroyed();
87+
super.onDestroy();
8088
}
8189

8290
@NonNull

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskViewModel.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import android.support.annotation.Nullable;
2323

2424
import com.example.android.architecture.blueprints.todoapp.R;
25-
import com.example.android.architecture.blueprints.todoapp.WeakActivityReference;
2625
import com.example.android.architecture.blueprints.todoapp.data.Task;
2726
import com.example.android.architecture.blueprints.todoapp.data.source.TasksDataSource;
2827
import com.example.android.architecture.blueprints.todoapp.data.source.TasksRepository;
@@ -56,15 +55,20 @@ public class AddEditTaskViewModel implements TasksDataSource.GetTaskCallback {
5655

5756
private boolean mIsDataLoaded = false;
5857

59-
private WeakActivityReference<AddEditTaskActivity> mAddEditTaskNavigator;
58+
private AddEditTaskNavigator mAddEditTaskNavigator;
6059

6160
AddEditTaskViewModel(Context context, TasksRepository tasksRepository) {
6261
mContext = context.getApplicationContext(); // Force use of Application Context.
6362
mTasksRepository = tasksRepository;
6463
}
6564

66-
void setNavigator(AddEditTaskActivity navigator) {
67-
mAddEditTaskNavigator = new WeakActivityReference<>(navigator);
65+
void onActivityCreated(AddEditTaskNavigator navigator) {
66+
mAddEditTaskNavigator = navigator;
67+
}
68+
69+
void onActivityDestroyed() {
70+
// Clear references to avoid potential memory leaks.
71+
mAddEditTaskNavigator = null;
6872
}
6973

7074
public void start(String taskId) {
@@ -140,8 +144,8 @@ private void updateTask(String title, String description) {
140144
}
141145

142146
private void navigateOnTaskSaved() {
143-
if (mAddEditTaskNavigator.get() != null) {
144-
mAddEditTaskNavigator.get().onTaskSaved();
147+
if (mAddEditTaskNavigator!= null) {
148+
mAddEditTaskNavigator.onTaskSaved();
145149
}
146150
}
147151
}

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsViewModel.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ public class StatisticsViewModel extends BaseObservable {
5555

5656
private final TasksRepository mTasksRepository;
5757

58-
5958
public StatisticsViewModel(Context context, TasksRepository tasksRepository) {
6059
mContext = context;
6160
mTasksRepository = tasksRepository;

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailActivity.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public class TaskDetailActivity extends BaseActivity implements TaskDetailNaviga
4646

4747
public static final int EDIT_RESULT_OK = RESULT_FIRST_USER + 3;
4848

49+
private TaskDetailViewModel mTaskViewModel;
50+
4951
@Override
5052
protected void onCreate(Bundle savedInstanceState) {
5153
super.onCreate(savedInstanceState);
@@ -56,11 +58,17 @@ protected void onCreate(Bundle savedInstanceState) {
5658

5759
TaskDetailFragment taskDetailFragment = findOrCreateViewFragment();
5860

59-
TaskDetailViewModel taskViewModel = findOrCreateViewModel();
60-
taskViewModel.setNavigator(this);
61+
mTaskViewModel = findOrCreateViewModel();
62+
mTaskViewModel.setNavigator(this);
6163

6264
// Link View and ViewModel
63-
taskDetailFragment.setViewModel(taskViewModel);
65+
taskDetailFragment.setViewModel(mTaskViewModel);
66+
}
67+
68+
@Override
69+
protected void onDestroy() {
70+
mTaskViewModel.onActivityDestroyed();
71+
super.onDestroy();
6472
}
6573

6674
@NonNull

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/taskdetail/TaskDetailViewModel.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
package com.example.android.architecture.blueprints.todoapp.taskdetail;
1818

1919
import android.content.Context;
20+
import android.support.annotation.Nullable;
2021

2122
import com.example.android.architecture.blueprints.todoapp.TaskViewModel;
22-
import com.example.android.architecture.blueprints.todoapp.WeakActivityReference;
2323
import com.example.android.architecture.blueprints.todoapp.data.source.TasksRepository;
2424
import com.example.android.architecture.blueprints.todoapp.tasks.TasksFragment;
2525

@@ -30,30 +30,35 @@
3030
*/
3131
public class TaskDetailViewModel extends TaskViewModel {
3232

33-
// Navigator has references to Activity so it must be wrapped to prevent leaks.
34-
private WeakActivityReference<TaskDetailActivity> mTaskDetailNavigator;
33+
@Nullable
34+
private TaskDetailNavigator mTaskDetailNavigator;
3535

3636
public TaskDetailViewModel(Context context, TasksRepository tasksRepository) {
3737
super(context, tasksRepository);
3838
}
3939

40-
public void setNavigator(TaskDetailActivity taskDetailNavigator) {
41-
mTaskDetailNavigator = new WeakActivityReference<>(taskDetailNavigator);
40+
public void setNavigator(TaskDetailNavigator taskDetailNavigator) {
41+
mTaskDetailNavigator = taskDetailNavigator;
42+
}
43+
44+
public void onActivityDestroyed() {
45+
// Clear references to avoid potential memory leaks.
46+
mTaskDetailNavigator = null;
4247
}
4348

4449
/**
4550
* Can be called by the Data Binding Library or the delete menu item.
4651
*/
4752
public void deleteTask() {
4853
super.deleteTask();
49-
if (mTaskDetailNavigator.get() != null) {
50-
mTaskDetailNavigator.get().onTaskDeleted();
54+
if (mTaskDetailNavigator != null) {
55+
mTaskDetailNavigator.onTaskDeleted();
5156
}
5257
}
5358

5459
public void startEditTask() {
55-
if (mTaskDetailNavigator.get() != null) {
56-
mTaskDetailNavigator.get().onStartEditTask();
60+
if (mTaskDetailNavigator != null) {
61+
mTaskDetailNavigator.onStartEditTask();
5762
}
5863
}
5964
}

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TaskItemViewModel.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,29 @@
1717
package com.example.android.architecture.blueprints.todoapp.tasks;
1818

1919
import android.content.Context;
20+
import android.support.annotation.Nullable;
2021

2122
import com.example.android.architecture.blueprints.todoapp.TaskViewModel;
22-
import com.example.android.architecture.blueprints.todoapp.WeakActivityReference;
2323
import com.example.android.architecture.blueprints.todoapp.data.source.TasksRepository;
2424

25+
import java.lang.ref.WeakReference;
26+
2527

2628
/**
2729
* Listens to user actions from the list item in ({@link TasksFragment}) and redirects them to the
2830
* Fragment's actions listener.
2931
*/
3032
public class TaskItemViewModel extends TaskViewModel {
3133

32-
// Navigator has references to Activity so it must be wrapped to prevent leaks.
33-
private WeakActivityReference<TasksActivity> mTaskItemNavigator;
34+
@Nullable
35+
private WeakReference<TaskItemNavigator> mNavigator;
3436

3537
public TaskItemViewModel(Context context, TasksRepository tasksRepository) {
3638
super(context, tasksRepository);
3739
}
3840

39-
void setNavigator(TasksActivity itemNavigator) {
40-
mTaskItemNavigator = new WeakActivityReference<>(itemNavigator);
41+
public void setNavigator(TaskItemNavigator navigator) {
42+
mNavigator = new WeakReference<>(navigator);
4143
}
4244

4345
/**
@@ -49,8 +51,8 @@ public void taskClicked() {
4951
// Click happened before task was loaded, no-op.
5052
return;
5153
}
52-
if (mTaskItemNavigator.get() != null) {
53-
mTaskItemNavigator.get().openTaskDetails(taskId);
54+
if (mNavigator != null && mNavigator.get() != null) {
55+
mNavigator.get().openTaskDetails(taskId);
5456
}
5557
}
5658
}

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksActivity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ protected void onCreate(Bundle savedInstanceState) {
6565
tasksFragment.setViewModel(mViewModel);
6666
}
6767

68+
@Override
69+
protected void onDestroy() {
70+
mViewModel.onActivityDestroyed();
71+
super.onDestroy();
72+
}
73+
6874
private TasksViewModel findOrCreateViewModel() {
6975
// In a configuration change we might have a ViewModel present. It's retained using the
7076
// Fragment Manager.

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksFragment.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public class TasksFragment extends Fragment {
5353
private TasksViewModel mTasksViewModel;
5454

5555
private TasksFragBinding mTasksFragBinding;
56+
private TasksAdapter mListAdapter;
5657

5758
public TasksFragment() {
5859
// Requires empty public constructor
@@ -123,6 +124,11 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
123124
setupRefreshLayout();
124125
}
125126

127+
@Override
128+
public void onDestroy() {
129+
mListAdapter.onDestroy();
130+
super.onDestroy();
131+
}
126132

127133
private void showFilteringPopUpMenu() {
128134
PopupMenu popup = new PopupMenu(getContext(), getActivity().findViewById(R.id.menu_filter));
@@ -175,7 +181,7 @@ public void onClick(View v) {
175181
private void setupListAdapter() {
176182
ListView listView = mTasksFragBinding.tasksList;
177183

178-
TasksAdapter mListAdapter = new TasksAdapter(
184+
mListAdapter = new TasksAdapter(
179185
new ArrayList<Task>(0),
180186
(TasksActivity) getActivity(),
181187
Injection.provideTasksRepository(getContext().getApplicationContext()),
@@ -197,7 +203,7 @@ private void setupRefreshLayout() {
197203

198204
public static class TasksAdapter extends BaseAdapter {
199205

200-
private final TasksActivity mTaskItemNavigator;
206+
@Nullable private TaskItemNavigator mTaskItemNavigator;
201207

202208
private final TasksViewModel mTasksViewModel;
203209

@@ -215,6 +221,10 @@ public TasksAdapter(List<Task> tasks, TasksActivity taskItemNavigator,
215221

216222
}
217223

224+
public void onDestroy() {
225+
mTaskItemNavigator = null;
226+
}
227+
218228
public void replaceData(List<Task> tasks) {
219229
setList(tasks);
220230
}
@@ -253,6 +263,7 @@ public View getView(int i, View view, ViewGroup viewGroup) {
253263
viewGroup.getContext().getApplicationContext(),
254264
mTasksRepository
255265
);
266+
256267
viewmodel.setNavigator(mTaskItemNavigator);
257268

258269
binding.setViewmodel(viewmodel);
@@ -270,6 +281,7 @@ public void onPropertyChanged(Observable observable, int i) {
270281
return binding.getRoot();
271282
}
272283

284+
273285
private void setList(List<Task> tasks) {
274286
mTasks = tasks;
275287
notifyDataSetChanged();

todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
import com.example.android.architecture.blueprints.todoapp.BR;
2929
import com.example.android.architecture.blueprints.todoapp.R;
30-
import com.example.android.architecture.blueprints.todoapp.WeakActivityReference;
3130
import com.example.android.architecture.blueprints.todoapp.addedittask.AddEditTaskActivity;
3231
import com.example.android.architecture.blueprints.todoapp.data.Task;
3332
import com.example.android.architecture.blueprints.todoapp.data.source.TasksDataSource;
@@ -68,13 +67,12 @@ public class TasksViewModel extends BaseObservable {
6867

6968
private final TasksRepository mTasksRepository;
7069

71-
// Navigator has references to Activity so it must be wrapped to prevent leaks.
72-
private WeakActivityReference<TasksActivity> mNavigator;
73-
7470
private final ObservableBoolean mIsDataLoadingError = new ObservableBoolean(false);
7571

7672
private Context mContext; // To avoid leaks, this must be an Application Context.
7773

74+
private TasksNavigator mNavigator;
75+
7876
public TasksViewModel(
7977
TasksRepository repository,
8078
Context context) {
@@ -85,8 +83,13 @@ public TasksViewModel(
8583
setFiltering(TasksFilterType.ALL_TASKS);
8684
}
8785

88-
void setNavigator(TasksActivity navigator) {
89-
mNavigator = new WeakActivityReference<>(navigator);
86+
void setNavigator(TasksNavigator navigator) {
87+
mNavigator = navigator;
88+
}
89+
90+
void onActivityDestroyed() {
91+
// Clear references to avoid potential memory leaks.
92+
mNavigator = null;
9093
}
9194

9295
public void start() {
@@ -157,8 +160,8 @@ public String getSnackbarText() {
157160
* Called by the Data Binding library and the FAB's click listener.
158161
*/
159162
public void addNewTask() {
160-
if (mNavigator.get() != null) {
161-
mNavigator.get().addNewTask();
163+
if (mNavigator != null) {
164+
mNavigator.addNewTask();
162165
}
163166
}
164167

0 commit comments

Comments
 (0)