android threading
TRANSCRIPT
Android Threading
Jussi Pohjolainen Tampere University of Applied Sciencs
UI Thread
• When Android app is launched one thread is created. This thread is called Main Thread or UI Thread
• UI Thread is responsible for dispatching events to widgets
• Avoid doing 0me consuming tasks in UI Thread since it leads to app that does not respond quickly
TesAng UI Responsivess public class ThreadExample extends Activity implements OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button button = new Button(this);
button.setText("Do Time Consuming task!");
setContentView(button);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
try {
for(int i=0; i<10; i++) {
System.out.println(i);
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Result
TesAng Separate Thread public class ThreadExample extends Activity implements OnClickListener, Runnable {
...
@Override
public void onClick(View v) {
Thread thread = new Thread(this);
thread.start();
}
@Override
public void run() {
try {
for(int i=0; i<10; i++) {
System.out.println(i);
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
How about influencing the UI? ... @Override public void run() { try { for(int i=0; i<10; i++) { button.setText("Iteration: " + i); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } ...
Problem
Why?
• Android UI Toolkit is not thread safe • If you want to manipulate UI, you must do it inside the UI thread
• How do you do it then? You can use – Activity.runOnUiThread(Runnable) – View.post(Runnable) – View.postDelayed(Runnable, long) – …
Activity.runOnUiThread(Runnable)
• The given acAon (Runnable) is executed immediately if current thread is UI thread
• If current thread is NOT UI thread, the acAon (Runnable) is posted to event queue of the UI Thread
Example of RunOnUiThread public class ThreadExample extends Activity implements OnClickListener, Runnable {
...
@Override
public void onClick(View v) {
Thread t = new Thread(this);
t.start();
}
public void run() {
// lengthy operation
try {
Thread.sleep(2000);
} catch (InterruptedException e) { }
runOnUiThread(new Update());
}
class Update implements Runnable {
// This action is posted to event queue
public void run() {
button.setText("Finished!");
}
}
}
View.post(Runnable) View.postDelayed(Runnable, Long)
• These methods are of view and are use for updaAng the view
• AcAon (Runnable) is placed on Message Queue
• Runnable acAon runs on UI Thread • postDelayed method for delayed acAon
Using post private int iteration; ... @Override
public void run() { try { for(int i=0; i<10; i++) { iteration = i; button.post(new InfluenceUIThread()); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } class InfluenceUIThread implements Runnable { public void run() { button.setText("Iteration = " + iteration); } }
Using Anonymous Inner Classes @Override
public void onClick(View v) { new Thread(new Runnable() { public void run() { try { for(int i=0; i<10; i++) { iteration = i; button.post(new Runnable() { public void run() { button.setText("Iteration = " + iteration); } }); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }
This can be really confusing...
AsyncTask
• Goal: take care thread management for you • Use it by subclassing it: class MyTask extends AsyncTask
• Override onPreExecute(), onPostExecute() and onProgressUpdate() – Invokes in UI Thread
• Override doInBackground() – Invokes in worker thread
Example (Google SDK) private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } new DownloadFilesTask().execute(url1, url2, url3);
Params, Progress, Result
public class ThreadExample extends Activity implements OnClickListener {
private Button button;
...
class MyBackgroundTask extends AsyncTask<Integer, Integer, Integer> {
protected Integer doInBackground(Integer... ints) {
int i = ints[0];
try {
for(i=0; i<10; i++) {
System.out.println("doInBackground!");
publishProgress(new Integer(i));
Thread.sleep(1000);
}
} catch(Exception e) {
e.printStackTrace();
}
return i;
}
protected void onProgressUpdate(Integer iteration) {
button.setText("Iteration = " + iteration);
}
protected void onPostExecute(Integer result) {
button.setText("Finished with result of: " + result);
}
}
}