'Best practice: weak reference to activity in static method

I need to reference an activity in several static methods. I'm curious to know the best practices to avoid memory leaks. Let's use examples:

Example 1:

static void hideKeyboard(Activity activity) {
   WeakReference<Activity> activityReference = new WeakReference<>(activity);
   // ... Call activityReference.get() when needed, check if null...
}

Example 2:

static void hideKeyboard(WeakReference<Activity> activityReference) {
   // ... Call activityReference.get() when needed, check if null...
}

So three questions:

  1. Do example 1 or 2 make any difference?
  2. I haven't seen methods being called this way much outside of subclasses of Thread or AsyncTask. Any reason why? Am I missing something?
  3. If the weak reference is used in a Thread or AsyncTask inside one of those methods, could memory still leak?


Solution 1:[1]

No, it doesn't make a difference. Garbage collection in Java works on the idea of GC roots. If a variable is a GC root or references by a GC root (including transitively) it cannot be garbage collected. Parameters to a function are a GC root- until the function returns none of its parameters can be collected. Since Activity is a parameter to your function, it will be uncollectable as long as that function is in the call stack. Using a WeakReference won't speed it up.

Threads and AsyncTasks (which are just wrappers around Thread really) are slightly different. Every running thread is also a GC root. But threads can have a long lifetime and exist beyond the lifecycle of the object. Here, using a WeakReference does possibly help because there isn't another reason it needs to be kept around (like the parameter in your sample).

Your example 2 is a bit better, it isn't blatantly unnecessary. But I question why its needed. In general when doing a Thread the pattern should be:

run() {
   do_async_work()
   update_ui()
}

update_ui() {
  Activity activity = weakReference.get()
  if(activity == null) {
     return
  }

  //update the UI
}

Doing it like this will prevent a lot of problems like needing to check the weak reference a dozen times.

Solution 2:[2]

There is absolutely no reason to use WeakReference in a parameter passed to a method, unless this parameter is being stored. If the parameter is only used in the method, you can just pass in the Activity reference.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 David Wasser