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
satya - Thursday, May 20, 2010 11:34:55 PM
android handler sample code
android handler sample code
satya - Friday, May 21, 2010 2:10:12 PM
Understand Message class as well
satya - Friday, May 21, 2010 2:12:08 PM
what is the class diagram exposing handler, message, and thread
what is the class diagram exposing handler, message, and thread
satya - Monday, May 24, 2010 10:47:10 PM
There are two variations of this
post - used for runnables
send - used for messages, and derived handlers
satya - Tuesday, May 25, 2010 1:16:33 PM
Here is a simple handler that sends 5 messages once every sec and stops
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);
}
}
satya - Tuesday, May 25, 2010 1:18:30 PM
Here is how you instantiate the handler on the main thread
//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();
}
satya - Tuesday, May 25, 2010 4:30:51 PM
A curious note is
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.
satya - Tuesday, May 25, 2010 4:33:28 PM
Here are the life stages
onCreate (life of the app starts)
(onRestart)
onStart (Partially visible)
onResume (fully visible)
onPause
onStop
onDestroy
satya - Tuesday, May 25, 2010 4:58:08 PM
Any queued messages will be called even if the app is "paused" or "stopped"
System will continue to process messages in the queue even after the UI is completely invisible.
satya - Tuesday, May 25, 2010 4:58:56 PM
is there a way to deplete android the message queue
is there a way to deplete android the message queue
Search for: is there a way to deplete android the message queue
satya - Tuesday, May 25, 2010 5:19:42 PM
Another way of constructing a message
int arg1
int arg2
Object obj
int what
satya - Tuesday, May 25, 2010 5:22:09 PM
you can use...
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()
satya - Wednesday, May 26, 2010 2:29:54 PM
Lets start with threads. Here is a simple runnable object
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.
satya - Wednesday, May 26, 2010 2:43:50 PM
Here is a more elaborate Runnable
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);
}
}
satya - Wednesday, May 26, 2010 3:14:40 PM
Here is how you can use this runnable to offload long running process
.....
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();
}
}
satya - Wednesday, May 26, 2010 3:17:27 PM
Here is the TestHandler2 that executes on the main thread
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);
}
}
satya - Wednesday, May 26, 2010 3:23:21 PM
Various states of a thread
blocked
new
runnable
terminated
timed_waiting
waiting
satya - Wednesday, May 26, 2010 3:23:48 PM
state diagram for a java thread
state diagram for a java thread
satya - Wednesday, May 26, 2010 3:26:05 PM
An excellent doc on thread states
satya - Wednesday, May 26, 2010 3:32:02 PM
when run exits
A thread dies naturally when its run() method exits normally
satya - Wednesday, May 26, 2010 3:33:23 PM
you are discouraged to stop
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.
satya - Wednesday, May 26, 2010 3:34:56 PM
on isAlive
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.