mobappdev (fall 2014): shared agendas, loopers, handlers, & threads
TRANSCRIPT
MobAppDev
Shared Agendas, Loopers, Handlers, & Threads
Vladimir Kulyukin
Outline● Shared Agenda Thread Pattern● Loopers, Handlers, & Threads● Using Loopers & Handlers to Update GUIs on the Main
Thread ProgressBarSimulatedFileDownload ProgressBarNetworkFileDownload
Shared Agenda Thread Pattern
Shared Agenda● Sequential processing of messages and tasks is
accomplished on Android via the Shared Agenda Thread pattern
● Agenda is an AI term frequently used in AI robotics
● Pipeline is an OS term commonly used in the concurrency literature
Shared Agenda● Shared Agenda Thread pattern is used on many robotic
platforms (ActivMedia robots is one example)● Shared Agenda pattern or something very similar to it
are used in many UI frameworks such as Swing or Adobe Flex
● On Android, the general idea is to use the Shared Agenda thread to push sequentially executable tasks off the main UI thread
Shared Agenda● Shared Agenda is a thread that holds a queue of
messages and tasks● A message (android.os.Message) is a data
structure for someone else to process● A task (java.lang.Runnable) is a exectable unit
of CPU work● In Java, Runnables are used to run some code on
different Threads
Shared Agenda
● Threads can push new messages or tasks onto the queue at any time
● When there are messages on the queue, the Shared Agenda processes them one after another
● When there are no tasks on the Shared Agenda, it blocks
Loopers, Handlers, & Threads
Definitions● Looper (android.os.Looper) is a class that turns a thread
into a shared agenda thread with a message/task queue● Handler (android.os.Handler) is a class whose objects
other threads can use to push messages/tasks to the shared agenda
● The term Looper emphasizes the fact that a Looper object loops over the message queue executing messages/tasks one after another
Threads & android.os.Handler
● Thread in Android has a MessageQueue● MessageQueue is a queue of Message objects● Handler is associated with a specific Thread and its
MessageQueue● Handler, after it is associated with a Thread, can send
Messages and Runnables to the Thread's MessageQueue and for the Looper to execute them as they come off the MessageQueue
android.os.Handler● Handlers are used to post Messages and Runnables on a specific Shared
Agenda Thread● You can enqueue Runnables with
post(Runnable) postAtTime(Runnable, long) postDelayed(Runnable, long)
● The enqueued Runnables are called as they are received● You can send messages with
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Messasge, int)
sendDelayedMessage(Message, long)
android.os.Looper
● Looper runs a message loop for a Thread● Handler is used in conjunction with a Looper● Looper.prepare() creates a message queue that
a Handler can use to post messages● Looper.loop() processes messages as long as
the Thread runs
Using Loopers & Handlers to Simulate File Download
source code is here
App Specs
● Develop an application that consists of one activity that displays one button
● A click on a button displays in a progress bar that works on the scale from 0 to 100
● The application simulates a file download and posts update messages to the main UI thread from a separate thread via a Handler
App Screenshots
UI XML<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/btnStartProgress" android:layout_width="match_parent" android:layout_height="200px" android:text="Download File" /></LinearLayout>
Declaration of UI Componentspublic class ProgressBarSimulatedFileDownloadActivity extends Activity
implements OnClickListener {
Button mBtnStartProgress; ProgressDialog mProgressBar; private int mProgressBarStatus=0; // Handler to post messages on the main thread from a non-main threads. private Handler mProgressBarHandler=new Handler(); private long mFileSize=0; static final String PROGRESS_MESSAGE="File Downloading . . ."; static final String COMPLETION_MESSAGE="Download complete."; …}
UI XML Inflation in onCreate()
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.progressbar_demo_layout); mBtnStartProgress =(Button) findViewById(R.id.btnStartProgress); mBtnStartProgress.setOnClickListener(this);}
Simulating File Download & Posting Messagespublic void simulateFileDownload() {
while( mProgressBarStatus < 100 ) { // do some task; downLoadFile method simulates a file download. mProgressBarStatus = downLoadFile(); // sleep for 500ms to simulate network traffic try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // Use the post method of the handler object // to send messages to the progress bar object on the main UI thread. mProgressBarHandler.post(new Runnable() { @Override public void run() { // show the status mProgressBar.setProgress(mProgressBarStatus); If( mProgressBarStatus>=100 ) mProgressBar.setMessage(COMPLETION_MESSAGE); }}); }
//after Download is complete If( mProgressBarStatus>=100 ) { // sleep 2 seconds, so that you can see the 100% try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // get rid of the progress bar object. mProgressBar.dismiss();
}
Computing Status of Progress Barprivate int downLoadFile() {
// pretend that the file size is 1,000,000 bytes = about 1MG
while (mFileSize <= 1000000) {
mFileSize++;
// scale the progress bar status, depending on the current size of the file.
if (mFileSize == 100000) { return 10; }
else if (mFileSize == 200000) { return 20; }
else if (mFileSize == 300000) { return 30; }
else if (mFileSize == 400000) { return 40; }
else if (mFileSize == 500000) { return 50; }
else if (mFileSize == 600000) { return 60; }
else if (mFileSize == 700000) { return 70; }
else if (mFileSize == 800000) { return 80; }
else if (mFileSize == 900000) { return 90; }
}
return 100; // the file has been downloaded
}
Mounting File Download on a Thread in onCreate()
// 1. Create a thread Thread thread = new Thread(){
public void run(){
simulateFileDownload();
}
};
// 2. Start the thread
thread.start();
Using Loopers & Handlers to Do Real File Download
source code is here
App Specs
● Develop an application that consists of one activity that displays one button
● A click on a button displays in a progress bar that works on the scale from 0 to 100
● The application downloads a real image file and posts update messages to the main UI thread from a separate thread via a Handler
App Screenshots
UI XML
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > <Button
android:id="@+id/btnStartProgress"
android:layout_width="match_parent"
android:layout_height="200px"
android:text="Download File" /> <ImageView
android:id="@+id/FileDownloadimageView"
android:layout_width="match_parent"
android:layout_height="wrap_content" /></LinearLayout>