mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-07-14 18:21:57 +00:00
fix various memory leaks
This commit is contained in:
parent
454a398a8d
commit
8e648ebed1
10 changed files with 107 additions and 90 deletions
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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){
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in a new issue