Welcome Android Developpers

Welcome Android Developpers
My name is Mathias Séguy, I am an Android Expert and Trainer and created the Android2EE company.

For full information, it’s here : Android2EE's Training
You can meet me on Google+, follow me on Twitter or on LinkedIn

Monday, November 21, 2011

Handler and Activity's life cycle, take care about orphan threads!!


Bandeau Conference
Hello,
You have an Activity which uses a Handler. You create your handler and overwrite the handleMessage method, you launch the handler’s thread and that’s it for the handler management… Most of us do such a thing and it’s a huge mistake!!! What happens to your thread when your activity pauses and resumes and worst when it dies and (re)creates? 
You thread becomes an orphan thread !

So you have written something like that :


(BAD CODE EXAMPLE DO NOT USE)
/**
 * The handler
 */
private final Handler slowDownDrawingHandler;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
// handler definition
slowDownDrawingHandler = new Handler() {
      /** (non-Javadoc)*/
      @Override
      public void handleMessage(Message msg) {
      super.handleMessage(msg);
      redraw();
      }
};
// Launching the Thread to update draw
Thread background = new Thread(new Runnable() {
      /**
       * The message exchanged between this thread and the handler
       */
      Message myMessage;

      // Overriden Run method
      public void run() {
try {
            while (true) {
      // Sleep
      Thread.sleep(100);
      // Do something
      myMessage = slowDownDrawingHandler.obtainMessage();
      // then send the message
      slowDownDrawingHandler.sendMessage(myMessage);
            }
      }
      } catch (Throwable t) {
      // just end the background thread
      }
      }
});
// start the thread
background.start();


Using such a code, when your activity pauses or dies your thread is still alive and become an orphan thread. Nothing can stop it, neither inter-acts with it and it continues to run. This is a big fail.
What is the right way to do it: You have to manage your thread state according to your activity state. In other words, when your activity pauses, you have to pauses your thread, when it resumes you have to resume your thread, when your activity dies, you thread must die….
A simple way to do that is to use two atomic Booleans (synchronized boolean), isPausing and isStopping, change their value in the onResume, onPause, onCreate and onDestroy methods of your activity and use that boolean to pause or stop your thread.
So the right code should look like that:
Good Code Example CAN BE USED
/** * The handler  */
private final Handler slowDownDrawingHandler;
/** * An atomic boolean to manage the external thread's destruction */
AtomicBoolean isRunning = new AtomicBoolean(false);
/** * An atomic boolean to manage the external thread's destruction */
AtomicBoolean isPausing = new AtomicBoolean(false);
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
// handler definition
slowDownDrawingHandler = new Handler() {
      @Override
      public void handleMessage(Message msg) {
      super.handleMessage(msg);
      redraw();
      }
};
// Launching the Thread to update draw
Thread background = new Thread(new Runnable() {
      /**
       * The message exchanged between this thread and the handler
       */
      Message myMessage;
      // Overriden Run method
      public void run() {
      try {
                  while (isRunning.get()) {
                  if(isPausing.get()) {
                        Thread.sleep(2000);
                  }else {
                  // Sleep
                  Thread.sleep(100);
                  // Do something
                  myMessage = slowDownDrawingHandler.obtainMessage();
                  // then send the message
                  slowDownDrawingHandler.sendMessage(myMessage);
            }
            }
            }
      } catch (Throwable t) {
      // just end the background thread
}
      }
});
// Initialize the threadSafe booleans
isRunning.set(true);
isPausing.set(false);
background.start();
}

/*(non-Javadoc) */
@Override
protected void onPause() {
//and don't forget to stop the thread
isPausing.set(true);
super.onPause();
}

/*(non-Javadoc) */
@Override
protected void onResume() {
//and don't forget to relaunch the thread
isPausing.set(false);
super.onResume();
}

/*(non-Javadoc) */
@Override
protected void onDestroy() {
//and don't forget to kill the thread
isRunning.set(false);
super.onDestroy();
}

So, Thanks who?
Thanks, Android2ee, the Android Programming Ebooks :o)

Mathias Séguy
mathias.seguy.it@gmail.com
Auteur Android2EE
Ebooks to learn Android Programming.
AndroidEvolution
Retrouvez moi sur Google+
Suivez moi sur Twitter
Rejoignez mon réseau LinkedIn ou Viadeo

No comments:

Post a Comment