Skip to content
Snippets Groups Projects
Commit 8cf02c5f authored by akwizgran's avatar akwizgran
Browse files

Merge branch '851-refresher-memory-leak' into 'master'

Fix memory leaks caused by periodic view refreshing tasks

This branch implements @goapunk's suggested solution to #851. Credit goes to @ernir for finding the bug and the initial solution, and @goapunk for the improved solution - I just did a quick implementation so we can get this fixed as quickly as possible.

Closes #851

See merge request !473
parents a6999a81 59316ae3
No related branches found
No related tags found
No related merge requests found
package org.briarproject.briar.android.blog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.CallSuper;
import android.support.annotation.UiThread;
import android.view.LayoutInflater;
......@@ -20,7 +22,7 @@ import javax.annotation.Nullable;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static org.briarproject.briar.android.util.UiUtils.MIN_RESOLUTION;
import static org.briarproject.briar.android.util.UiUtils.MIN_DATE_RESOLUTION;
@UiThread
@MethodsNotNullByDefault
......@@ -32,8 +34,9 @@ abstract class BasePostFragment extends BaseFragment {
private static final Logger LOG =
Logger.getLogger(BasePostFragment.class.getName());
private final Handler handler = new Handler(Looper.getMainLooper());
protected MessageId postId;
private View view;
private ProgressBar progressBar;
private BlogPostViewHolder ui;
private BlogPostItem post;
......@@ -50,7 +53,7 @@ abstract class BasePostFragment extends BaseFragment {
if (p == null) throw new IllegalStateException("No post ID in args");
postId = new MessageId(p);
view = inflater.inflate(R.layout.fragment_blog_post, container,
View view = inflater.inflate(R.layout.fragment_blog_post, container,
false);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
progressBar.setVisibility(VISIBLE);
......@@ -83,21 +86,19 @@ abstract class BasePostFragment extends BaseFragment {
refresher = new Runnable() {
@Override
public void run() {
if (ui == null) return;
LOG.info("Updating Content...");
ui.updateDate(post.getTimestamp());
view.postDelayed(refresher, MIN_RESOLUTION);
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
}
};
LOG.info("Adding Handler Callback");
view.postDelayed(refresher, MIN_RESOLUTION);
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
}
private void stopPeriodicUpdate() {
if (refresher != null && ui != null) {
if (refresher != null) {
LOG.info("Removing Handler Callback");
view.removeCallbacks(refresher);
handler.removeCallbacks(refresher);
}
}
......
......@@ -105,6 +105,7 @@ public class FeedFragment extends BaseFragment implements
public void onStart() {
super.onStart();
feedController.onStart();
list.startPeriodicUpdate();
loadPersonalBlog();
loadBlogPosts(false);
}
......@@ -157,7 +158,6 @@ public class FeedFragment extends BaseFragment implements
handleDbException(exception);
}
});
list.startPeriodicUpdate();
}
@Override
......
......@@ -33,7 +33,7 @@ import static android.text.format.DateUtils.WEEK_IN_MILLIS;
public class UiUtils {
public static final long MIN_RESOLUTION = MINUTE_IN_MILLIS;
public static final long MIN_DATE_RESOLUTION = MINUTE_IN_MILLIS;
public static final int TEASER_LENGTH = 320;
public static final float GREY_OUT = 0.5f;
......@@ -51,15 +51,16 @@ public class UiUtils {
FORMAT_SHOW_DATE | FORMAT_ABBREV_TIME | FORMAT_ABBREV_MONTH;
long diff = System.currentTimeMillis() - time;
if (diff < MIN_RESOLUTION) return ctx.getString(R.string.now);
if (diff < MIN_DATE_RESOLUTION) return ctx.getString(R.string.now);
if (diff >= DAY_IN_MILLIS && diff < WEEK_IN_MILLIS) {
// also show time when older than a day, but newer than a week
return DateUtils.getRelativeDateTimeString(ctx, time,
MIN_RESOLUTION, WEEK_IN_MILLIS, flags).toString();
MIN_DATE_RESOLUTION, WEEK_IN_MILLIS, flags).toString();
}
// otherwise just show "...ago" or date string
return DateUtils.getRelativeTimeSpanString(time,
System.currentTimeMillis(), MIN_RESOLUTION, flags).toString();
System.currentTimeMillis(),
MIN_DATE_RESOLUTION, flags).toString();
}
public static SpannableStringBuilder getTeaser(Context ctx, Spanned body) {
......
......@@ -2,6 +2,8 @@ package org.briarproject.briar.android.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
import android.util.AttributeSet;
......@@ -17,14 +19,15 @@ import java.util.logging.Logger;
import javax.annotation.Nullable;
import static org.briarproject.briar.android.util.UiUtils.MIN_RESOLUTION;
import static org.briarproject.briar.android.util.UiUtils.MIN_DATE_RESOLUTION;
public class BriarRecyclerView extends FrameLayout {
private static final long DEFAULT_REFRESH_INTERVAL = MIN_RESOLUTION;
private static final Logger LOG =
Logger.getLogger(BriarRecyclerView.class.getName());
private final Handler handler = new Handler(Looper.getMainLooper());
private RecyclerView recyclerView;
private TextView emptyView;
private ProgressBar progressBar;
......@@ -192,18 +195,19 @@ public class BriarRecyclerView extends FrameLayout {
@Override
public void run() {
LOG.info("Updating Content...");
recyclerView.getAdapter().notifyDataSetChanged();
postDelayed(refresher, DEFAULT_REFRESH_INTERVAL);
Adapter adapter = recyclerView.getAdapter();
adapter.notifyItemRangeChanged(0, adapter.getItemCount());
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
}
};
LOG.info("Adding Handler Callback");
postDelayed(refresher, DEFAULT_REFRESH_INTERVAL);
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
}
public void stopPeriodicUpdate() {
if (refresher != null) {
LOG.info("Removing Handler Callback");
removeCallbacks(refresher);
handler.removeCallbacks(refresher);
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment