package org.wikipedia.concurrency;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

public class CallbackTask<T> extends SaneAsyncTask<T> {
    public interface Callback<T> {
        void success(T row);
    }

    public interface Task<T> {
        T execute();
    }

    @NonNull private final Task<T> task;
    @Nullable private final Callback<T> callback;

    public static <T> void execute(@NonNull Task<T> task) {
        execute(task, null);
    }

    public static <T> void execute(@NonNull Task<T> task, @Nullable Callback<T> callback) {
        new CallbackTask<>(task, callback).execute();
    }

    CallbackTask(@NonNull Task<T> task, @Nullable Callback<T> callback) {
        this.task = task;
        this.callback = callback;
    }

    @Override public T performTask() throws Throwable {
        return task.execute();
    }

    @Override public void onFinish(T result) {
        super.onFinish(result);
        if (callback != null) {
            callback.success(result);
        }
    }
}

package org.wikipedia.concurrency;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

public class CallbackTask<T> extends SaneAsyncTask<T> {
    public interface Callback<T> {
        void success(T row);
    }

    public interface Task<T> {
        T execute();
    }

    @NonNull private final Task<T> task;
    @Nullable private Callback<T> callback;

    public static <T> void execute(@NonNull Task<T> task) {
        execute(task, null);
    }

    public static <T> void execute(@NonNull Task<T> task, @Nullable Callback<T> callback) {
        new CallbackTask<>(task, callback).execute();
    }

    CallbackTask(@NonNull Task<T> task, @Nullable Callback<T> callback) {
        this.task = task;
        this.callback = callback;
    }

    @Override public T performTask() throws Throwable {
        return task.execute();
    }

    @Override public void onFinish(T result) {
        super.onFinish(result);
        if (callback != null) {
            callback.success(result);
            callback = null;
        }
    }
}

Fix possible memory leak in feed.
Fix possible memory leak in feed.

I've observed a memory leak (on API 17) apparently stemming from the new
functionality to fill in the bookmark icon when the featured article is
detected to be part of a reading list.

This seems to be caused by us passing an anonymous instance of a
CallbackTask.Callback object from FeaturedArticleView, which contains
references to $this, which contains a reference to the activity context.

This patch solves the leak by modifying the CallbackTask to no longer hold
on to a reference of Callback, and instead null it out immediately after
it's called.

Change-Id: I768e24dab7f39652ec741a5d6f9821db7de4f2bd
