Search code examples
androiduser-interfacememory-leakshandlerandroid-handler

Using a Static Handler to update the UI thread


When using a background thread to do work, typically you'd update the UI through a Handler.

One way to do this was defining a handler at the class level as outlined in this answer, and this answer

final Handler handler = new Handler(){
  @Override
  public void handleMessage(Message msg) {
    //update UI or call class methods here
  }
};

However, this construct would result in the following warning

Handler class should be static otherwise memory leaks might occur

Another way to do this was to use a static inner class as outlined in this answer, and this answer

static class MyHandler extends Handler {
    private final WeakReference<Type> myWeakReference; 

    MyHandler(Type reference) {
        myWeakReference = new WeakReference<Type>(reference);
    }
    @Override
    public void handleMessage(Message msg)
    {
       //Update UI or call class methods here using weak reference
    }
}

However, this form of constructor has been Deprecated according to the Android docs.

public Handler ()

This constructor is deprecated. Implicitly choosing a Looper during Handler construction can lead to bugs where operations are silently lost (if the Handler is not expecting new tasks and quits), crashes (if a handler is sometimes created on a thread without a Looper active), or race conditions, where the thread a handler is associated with is not what the author anticipated. Instead, use an Executor or specify the Looper explicitly, using Looper#getMainLooper, {link android.view.View#getHandler}, or similar. If the implicit thread local behavior is required for compatibility, use new Handler(Looper.myLooper()) to make it clear to readers.

How should updating the UI from a Handler be done currently, and should a Handler still be used for this purpose.


Solution

  • As you stated the docs, it says to use Looper.getMainLooper(), just change your code to:

    MyHandler(Type reference) {
        super(Looper.getMainLooper());
        myWeakReference = new WeakReference<Type>(reference);
    }
    

    to update the UI from the main/UI thread.