This covers a) handlers b) sample code for handlers and messages c) offloading long processes to threads d) instantiating handlers e) getting messages to work with handlers f) working with threads

base read

android handler sample code

Search for: android handler sample code

Understand Message class as well

what is the class diagram exposing handler, message, and thread


post - used for runnables
send - used for messages, and derived handlers

public class TestHandler1 extends Handler
{
   public static final String tag = "TestHandler1";
   private int count = 0;
   private HelloWorld parentActivity = null; 
   
   public TestHandler1(HelloWorld inParentActivity)
   {
      parentActivity = inParentActivity;
   }

   @Override
   public void handleMessage(Message msg) 
   {
      String pm = new String(
            "message called:" + count + ":" + 
            msg.getData().getString("message"));
      
      Log.d(tag,pm);
      this.printMessage(pm);
      
      if (count > 5)
      {
         return;
      }
      count++;
      sendTestMessage(1);
   }

   public void sendTestMessage(long interval)
   {
      Message m = this.obtainMessage();
      prepareMessage(m);
      this.sendMessageDelayed(m, interval * 1000);
   }
   public void sendTestMessages()
   {
      count = 0;
      sendTestMessage(1);
   }
   public void prepareMessage(Message m)
   {
      Bundle b = new Bundle();
      b.putString("message", "Hello World");
      return ;
      
   }
   private void printMessage(String xyz)
   {
      parentActivity.appendText(xyz);
   }
}

//Call the test througha menu item
if (item.getItemId() == R.id.menu_handler1)
{
  this.testHandler();
  return true;
}
......
......

//get a local variable in the main activity
private TestHandler1 th = null;

private void testHandler()
{
   if (th == null)
   {
	  th = new TestHandler1(this);
	  this.appendText("Creating a new handler");
   }
  this.appendText("Starting to send messages");
  th.sendTestMessages();
}

if I let the handler to continuously fire messages by having the each message post another one to the queue, I have noticed that the queue continues to process even if the app is paused (partial visibility) or stopped (it is not in the foreground) any more.

That brought me to my next investigation of is there any cleanup that needs to be done in the life span methods.


onCreate (life of the app starts)
       (onRestart)
       onStart (Partially visible)
               onResume (fully visible)
               onPause  
       onStop
onDestroy

System will continue to process messages in the queue even after the UI is completely invisible.

is there a way to deplete android the message queue

Search for: is there a way to deplete android the message queue


int arg1
int arg2
Object obj
int what

arg1, arg2, and obj instead of usign the setdata(), a heavier operation.

you can use the "what" to identify messages that you can deplete from the queue during onPause or onStop as the case may be.

You may also choose to do nothing in onstop or onpause as the system may brign back your process through onRestart()


public class TestRunnable implements Runnable
{
   public static String tag = "TestRunnable";
   public void run()
   {
      Log.d(tag,"start execution");
   }
}

Runnable is one of the simplest, almost elegant, interfaces. It has just one method. It should obtain context information from its constructor when context is required to run. You will some examples later.


public class TestRunnable implements Runnable
{
   Handler mainThreadHandler = null;
   int count = 0;
   public TestRunnable(Handler h)
   {
      mainThreadHandler = h;
   }
   public static String tag = "TestRunnable";
   public void run()
   {
      Log.d(tag,"start execution");
      informStart();
      for(int i=1;i <= 10;i++)
      {
         Utils.sleepForInSecs(1);
         informMiddle(i);
      }
      informFinish();
   }
   
   public void informMiddle(int count)
   {
      Message m = this.mainThreadHandler.obtainMessage();
      m.setData(Utils.getStringAsABundle("done:" + count));
      this.mainThreadHandler.sendMessage(m);
   }
   
   public void informStart()
   {
      Message m = this.mainThreadHandler.obtainMessage();
      m.setData(Utils.getStringAsABundle("starting run"));
      this.mainThreadHandler.sendMessage(m);
   }
   public void informFinish()
   {
      Message m = this.mainThreadHandler.obtainMessage();
      m.setData(Utils.getStringAsABundle("Finishing run"));
      this.mainThreadHandler.sendMessage(m);
   }
}

.....
if (item.getItemId() == R.id.menu_test_thread)
{
   this.testThread();
   return true;
}
.....
Handler threadHandler = null;
Thread t = null;
private void testThread()
{
   if (threadHandler == null)
   {
     threadHandler = new TestHandler2(this);
      t = new Thread(new TestRunnable(threadHandler));
   }
   if (t.isAlive())
   {
     Log.d(tag, "thread is alive");
   }
   else
   {
     Log.d(tag, "thread is not started. starting now");
     t.start();
   }
}

public class TestHandler2 extends Handler
{
   public static final String tag = "TestHandler2";
   private HelloWorld parentActivity = null; 
   
   public TestHandler2(HelloWorld inParentActivity)
   {
      parentActivity = inParentActivity;
   }

   @Override
   public void handleMessage(Message msg) 
   {
      String pm = Utils.getStringFromABundle(msg.getData());
            
      Log.d(tag,pm);
      this.printMessage(pm);
   }

   private void printMessage(String xyz)
   {
      parentActivity.appendText(xyz);
   }
}

blocked
new
runnable
terminated
timed_waiting
waiting

state diagram for a java thread

Search for: state diagram for a java thread

An excellent doc on thread states

A thread dies naturally when its run() method exits normally

The stop() method causes a sudden termination of a Thread's run() method. If the run() method performs critical or sensitive calculations, stop() may leave the program in an inconsistent or awkward state. Normally, you should not call Thread's stop() method but arrange for a gentler termination such as setting a flag to indicate to the run() method that it should exit.

A final word about thread state: the programming interface for the Thread class includes a method called isAlive(). The isAlive() method returns true if the thread has been started and not stopped. Thus, if the isAlive() method returns false you know that the thread is either a "New Thread" or "Dead". If the isAlive() method returns true, you know that the thread is either "Runnable" or "Not Runnable". You cannot differentiate between a "New Thread" and a "Dead" thread; nor can you differentiate between a "Runnable" thread and a "Not Runnable" thread.