• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Thread to UI Handler, best practice ?

RLScott

Newbie
I'm trying to clean up some thread to UI communication code. In this application, a Worker thread is supposed to remaining running for the lifetime of the app, especially through screen rotations or other events that cause the main activity to be destroyed and re-created. I want to avoid memory leaks and null pointer references. The only communication that is necessary is to nudge the main activity with a single integer code. Here is a condensed version of the essentials (I think). Any comments on the approach I have taken would be greatly appreciated.

Code:
public class Main extends Activity {
  public static WeakReference<Main> gMain;
  public final static MainHandler gMainHand = new MainHandler();
  private final static Worker worker = new Worker();

  private static class MainHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
      Main mainNow = gMain.get();
      if(mainNow == null)
        return;
      switch(msg.what)
      {
        case 42:
           /* Do stuff refering to Main variables through mainNow */
           break;
      }
    } //..end of handleMessage
  }  //..end of MainHandler class

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    gMain = new WeakRefernce<Main>(this);
  }

  /* some time later:*/ worker.start();
}  //..end of Main activity class

public class Worker extends Thread {
  public void run()
  {
    /* at some point */  Main.gMainHand.sendEmptyMessage(42);
  }
}  //..end of Worker thread class
 
Here is another way of doing it that has the advantage of being able to post runnables and does not require a custom Handler class extension.

Code:
public class Main extends Activity {
  public static WeakReference<Main> gMain;
  public final Handler handler = new Handler();  //..no longer static or custom
  private final static Worker worker = new Worker();
  Runnable doSomethingToUI;
  @Override
  public void onCreate(Bundle savedInstanceState) {
    gMain = new WeakReference<Main>(this);
    doSomethingToUI = new Runnable() {public void run() {
       /*---something affecting UI---*/
  }};
  }    //..end of onCreate()
  /* some time later:*/ worker.start();
}  //..end of Main activity class
public class Worker extends Thread {
  public void run() {
    //..At some point we may do this:
  Main mainNow = Main.gMain.get();    //..strong reference from WeakReference
  if(mainNow != null){
    mainNow.handler.post(mainNow.doSomethingToUI)};
. . . .
}  //..end of Worker thread class

By fetching the strong reference to Main in the worker thread instead of the static custom Handler class, we now get to access all the non-static members of Main normally without having to use an explicit "nowMain." prefix.
 
Or use AsyncTask if you want to do something to the UI from a parallel thread.
 
Or use AsyncTask if you want to do something to the UI from a parallel thread.
Does an AsyncTask work when the spawning Activity is destroyed and re-created during a screen rotation? I was under the impression that an AsyncTask holds a strong reference to the Activity that created it, and that postings from the AsyncTask went to that instance. In the case of an Activity re-instantiation during the lifetime of the AsyncTask, the AsyncTask posts its results to a now-dead instance of the spawning Activity, not the instance current active. The only reason the old instance did not go away is because the AsyncTask holds the strong reference to it. Do I have that wrong?
 
Back
Top Bottom