fix various memory leaks

This commit is contained in:
Phillip Thelen 2017-02-01 13:46:28 +01:00
parent 454a398a8d
commit 8e648ebed1
10 changed files with 107 additions and 90 deletions

View file

@ -29,6 +29,7 @@ import com.habitrpg.android.habitica.ui.activities.LoginActivity;
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import com.raizlabs.android.dbflow.config.FlowManager;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;
import org.solovyev.android.checkout.Billing;
import org.solovyev.android.checkout.Cache;
@ -56,6 +57,9 @@ public abstract class HabiticaBaseApplication extends MultiDexApplication {
@Inject
CrashlyticsProxy crashlyticsProxy;
private static AppComponent component;
public RefWatcher refWatcher;
/**
* For better performance billing class should be used as singleton
*/
@ -123,6 +127,11 @@ public abstract class HabiticaBaseApplication extends MultiDexApplication {
@Override
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
setupDagger();
crashlyticsProxy.init(this);
setupLeakCanary();
@ -177,10 +186,7 @@ public abstract class HabiticaBaseApplication extends MultiDexApplication {
protected abstract AppComponent initDagger();
private void setupLeakCanary() {
// LeakCanary 1.3.1 has problems on Marshmallow; can remove check once updated with fixes
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
LeakCanary.install(this);
}
refWatcher = LeakCanary.install(this);
}
private void setupFlowManager() {

View file

@ -36,7 +36,7 @@ public class PopupNotificationsManager {
private PopupNotificationsManager(APIHelper apiHelper, Context context) {
this.apiHelper = apiHelper;
this.seenNotifications = new HashMap<>();
this.context = context;
this.context = context.getApplicationContext();
}
public static PopupNotificationsManager getInstance(APIHelper apiHelper, Context context) {

View file

@ -48,7 +48,7 @@ public class TaskAlarmManager {
private TaskAlarmManager(Context context) {
HabiticaBaseApplication.getComponent().inject(this);
this.context = context;
this.context = context.getApplicationContext();
EventBus.getDefault().register(this);
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}

View file

@ -1,17 +1,16 @@
package com.habitrpg.android.habitica.helpers.notifications;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.RemoteMessage;
import com.habitrpg.android.habitica.APIHelper;
import com.habitrpg.android.habitica.HabiticaApplication;
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import com.magicmicky.habitrpgwrapper.lib.models.PushDevice;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.RemoteMessage;
import com.habitrpg.android.habitica.APIHelper;
import com.habitrpg.android.habitica.HabiticaApplication;
import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback;
import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import com.magicmicky.habitrpgwrapper.lib.models.PushDevice;
import java.util.HashMap;
import java.util.Map;
@ -55,11 +54,11 @@ public class PushNotificationManager {
public static PushNotificationManager getInstance(Context context) {
if(instance == null) {
instance = new PushNotificationManager(context);
instance = new PushNotificationManager(context.getApplicationContext());
}
instance.refreshedToken = instance.sharedPreferences.getString(DEVICE_TOKEN_PREFERENCE_KEY, "");
instance.context = context;
instance.context = context.getApplicationContext();
return instance;
}

View file

@ -882,7 +882,10 @@ public class MainActivity extends BaseActivity implements Action1<Throwable>, Ha
}
private void setTranslatedFragmentTitle(BaseMainFragment fragment){
if(fragment!= null && fragment.customTitle() != null){
if (getSupportActionBar() == null) {
return;
}
if(fragment!= null && fragment.isAdded() && fragment.customTitle() != null){
getSupportActionBar().setTitle(fragment.customTitle());
}
else if(user != null && user.getProfile() != null){

View file

@ -19,7 +19,6 @@ import com.raizlabs.android.dbflow.sql.language.Select;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import android.app.Activity;
import android.content.Context;
import android.databinding.ObservableArrayList;
import android.support.v7.widget.RecyclerView;
@ -43,7 +42,7 @@ public abstract class BaseTasksRecyclerViewAdapter<VH extends BaseTaskViewHolder
private final String userID;
int layoutResource;
String taskType;
public String taskType;
Context context;
protected List<Task> content;
protected List<Task> filteredContent;
@ -53,7 +52,7 @@ public abstract class BaseTasksRecyclerViewAdapter<VH extends BaseTaskViewHolder
Context newContext, String userID) {
this.setHasStableIds(true);
this.taskType = taskType;
this.context = newContext;
this.context = newContext.getApplicationContext();
this.tagsHelper = tagsHelper;
this.userID = userID;
this.filteredContent = new ArrayList<>();
@ -99,72 +98,9 @@ public abstract class BaseTasksRecyclerViewAdapter<VH extends BaseTaskViewHolder
return LayoutInflater.from(parent.getContext()).inflate(layoutResource, parent, false);
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
EventBus.getDefault().register(this);
}
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
EventBus.getDefault().unregister(this);
}
@Subscribe
public void onEvent(FilterTasksByTagsCommand cmd) {
filter();
}
@Subscribe
public void onEvent(TaskCheckedCommand evnt) {
if (!taskType.equals(evnt.Task.getType()))
public void updateTask(Task task) {
if (!taskType.equals(task.getType()))
return;
if (evnt.completed && evnt.Task.getType().equals("todo")) {
// remove from the list
content.remove(evnt.Task);
}
this.updateTask(evnt.Task);
filter();
}
@Subscribe
public void onEvent(TaskUpdatedEvent evnt) {
if (!taskType.equals(evnt.task.getType()))
return;
this.updateTask(evnt.task);
filter();
}
@Subscribe
public void onEvent(TaskCreatedEvent evnt) {
if (!taskType.equals(evnt.task.getType()))
return;
content.add(0, evnt.task);
filter();
}
@Subscribe
public void onEvent(TaskRemovedEvent evnt) {
Task taskToDelete = null;
for (Task t : content) {
if (t.getId().equals(evnt.deletedTaskId)) {
taskToDelete = t;
break;
}
}
if (taskToDelete != null) {
content.remove(taskToDelete);
filter();
}
}
private void updateTask(Task task) {
int i;
for (i = 0; i < this.content.size(); ++i) {
if (content.get(i).getId().equals(task.getId())) {
@ -174,9 +110,10 @@ public abstract class BaseTasksRecyclerViewAdapter<VH extends BaseTaskViewHolder
if (i < content.size()) {
content.set(i, task);
}
filter();
}
private void filter() {
public void filter() {
if (this.tagsHelper == null || this.tagsHelper.howMany() == 0) {
filteredContent = content;
} else {
@ -184,7 +121,7 @@ public abstract class BaseTasksRecyclerViewAdapter<VH extends BaseTaskViewHolder
filteredContent.addAll(this.tagsHelper.filter(content));
}
((Activity) context).runOnUiThread(this::notifyDataSetChanged);
this.notifyDataSetChanged();
}
public void loadContent(boolean forced) {
@ -228,4 +165,40 @@ public abstract class BaseTasksRecyclerViewAdapter<VH extends BaseTaskViewHolder
public boolean loadFromDatabase(){
return true;
}
public void checkTask(Task task, Boolean completed) {
if (!taskType.equals(task.getType()))
return;
if (completed && task.getType().equals("todo")) {
// remove from the list
content.remove(task);
}
this.updateTask(task);
filter();
}
public void addTask(Task task) {
if (!taskType.equals(task.getType()))
return;
content.add(0, task);
filter();
}
public void removeTask(String deletedTaskId) {
Task taskToDelete = null;
for (Task t : content) {
if (t.getId().equals(deletedTaskId)) {
taskToDelete = t;
break;
}
}
if (taskToDelete != null) {
content.remove(taskToDelete);
filter();
}
}
}

View file

@ -8,6 +8,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.habitrpg.android.habitica.HabiticaApplication;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.events.DisplayTutorialEvent;
import com.habitrpg.android.habitica.helpers.AmplitudeManager;
@ -17,6 +18,7 @@ import com.raizlabs.android.dbflow.runtime.transaction.BaseTransaction;
import com.raizlabs.android.dbflow.runtime.transaction.TransactionListener;
import com.raizlabs.android.dbflow.sql.builder.Condition;
import com.raizlabs.android.dbflow.sql.language.Select;
import com.squareup.leakcanary.RefWatcher;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.EventBusException;
@ -116,6 +118,8 @@ public abstract class BaseFragment extends DialogFragment {
}
super.onDestroyView();
RefWatcher refWatcher = HabiticaApplication.getInstance(getContext()).refWatcher;
refWatcher.watch(this);
}
public String getDisplayedClassName() {

View file

@ -13,7 +13,12 @@ import android.view.ViewGroup;
import com.habitrpg.android.habitica.APIHelper;
import com.habitrpg.android.habitica.R;
import com.habitrpg.android.habitica.components.AppComponent;
import com.habitrpg.android.habitica.events.TaskCreatedEvent;
import com.habitrpg.android.habitica.events.TaskRemovedEvent;
import com.habitrpg.android.habitica.events.TaskUpdatedEvent;
import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand;
import com.habitrpg.android.habitica.events.commands.FilterTasksByTagsCommand;
import com.habitrpg.android.habitica.events.commands.TaskCheckedCommand;
import com.habitrpg.android.habitica.helpers.TagsHelper;
import com.habitrpg.android.habitica.ui.adapter.tasks.BaseTasksRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.DailiesRecyclerViewHolder;
@ -29,6 +34,7 @@ import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser;
import com.magicmicky.habitrpgwrapper.lib.models.tasks.Task;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import javax.inject.Inject;
import javax.inject.Named;
@ -226,4 +232,29 @@ public class TaskRecyclerViewFragment extends BaseFragment implements View.OnCli
String getClassName() {
return this.classType;
}
@Subscribe
public void onEvent(FilterTasksByTagsCommand cmd) {
recyclerAdapter.filter();
}
@Subscribe
public void onEvent(TaskCheckedCommand event) {
recyclerAdapter.checkTask(event.Task, event.completed);
}
@Subscribe
public void onEvent(TaskUpdatedEvent event) {
recyclerAdapter.updateTask(event.task);
}
@Subscribe
public void onEvent(TaskCreatedEvent event) {
recyclerAdapter.addTask(event.task);
}
@Subscribe
public void onEvent(TaskRemovedEvent event) {
recyclerAdapter.removeTask(event.deletedTaskId);
}
}

View file

@ -661,5 +661,6 @@ public class TasksFragment extends BaseMainFragment implements OnCheckedChangeLi
@Override
public String customTitle() { return getString(R.string.sidebar_tasks); }
public String customTitle() {
return getString(R.string.sidebar_tasks); }
}

View file

@ -150,7 +150,7 @@ public interface ApiService {
@POST("user/sleep")
Observable<HabitResponse<Void>> sleep();
Observable<HabitResponse<Boolean>> sleep();
@POST("user/revive")
Observable<HabitResponse<HabitRPGUser>> revive();