1
\$\begingroup\$

Oftentimes I find myself using context inside threads, multiple times. The problem is that I do not want to hold a long-lived strong reference of it in my threads to avoid leaking it. I keep a weakReference to it in global space and when my activity dies, it will obviously not prevent any GC events or such.

I have made the following approach to using context in threads:

public interface UseContext<Result, Param extends Context> {
    Result work(Param context);
}

public static <T extends Context, Result> Optional<Result> useContext(final WeakReference<T> reference,
                                                                      final UseContext<Result, T> task) {

    final T context;
    final boolean contextLost = (context = reference.get()) == null;
    final boolean isActivity = context instanceof Activity;

    if (contextLost)
        return Optional.absent();
    final boolean activityIsFinishing = (isActivity && ((Activity) context).isFinishing());
    if (activityIsFinishing)
        return Optional.absent();

    return Optional.fromNullable(task.work(context));
}

Whenever I have to use context inside a thread, I do this (example) :

        MiscUtils.useContext(reference, activity -> {
            activity.runOnUiThread(() -> Toast.makeText(activity, message, Toast.LENGTH_SHORT).show());
            return null;
        });

Is this a correct approach? Also, I'm not entirely convinced that holding a strong reference to Context in global space and using it in runnable is a bad idea. I understand that it was something to do with anonymous inner classes causing memory leaks.

\$\endgroup\$
1
\$\begingroup\$

I think it's a bit of overhead.

Depending on what you need to do with the Context, you can the Application Context instead of the Activity itself. This context is available while the process runs, so there no leakage is possible.

In my experience, Activities being leaked have been caused by singletons initialized by passing the Activity instance (as a Context). Be careful also with Views, as they hold a reference to the Context.

Using the StrictMode with the setClassInstanceLimit and a bit of logging has helped me catch these leaks quite fast.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.