Is it good approach to have one HandlerThread
in app for making different time spending actions,like,for example,sorting or maybe even for working with web/file streams?
What is better to use for such purposes: several AsyncTask
's, several Thread
s or one HandlerThread
like
http://hi-android.info/src/android/webkit/WebViewWorker.java.html
?
AsyncTask are similar, in fact, they make use of Handler , but doesn't run in the UI thread, so it's good for fetching data, for instance fetching web services. Later you can interact with the UI. Thread however can't interact with the UI, provide more "basic" threading and you miss all the abstractions of AsyncTask .
Threads are generic processing tasks that can do most things, but one thing they cannot do is update the UI. Handlers on the other hand are background threads that allow you to communicate with the UI thread (update the UI).
A Handler is a component that can be attached to a thread and then made to perform some action on that thread via simple messages or Runnable tasks. It works in conjunction with another component, Looper , which is in charge of message processing in a particular thread.
You must delegate time consuming operation (network, database access, ...) to some type of worker threads. It is not acceptable to block the main (UI) thread.
AsyncTask
is a high level object. It takes care of the thread handling and inter-thread communications for you, using an internal Handler
and an Executor
. It has been designed for the (very) common case of doing something in the background and pushing the result to the UI.
Using Handler
and HandlerThread
(or event Thread
) directly gives you more flexibility, at the cost of a more complex code, and some subtle pitfalls (e.g. How to Leak a Context: Handlers & Inner Classes).
One choice you have make is to execute the tasks serially or in parallel. A HandlerThread
would serialize them. For AsyncTask
it depends on the Android version (but this can be overridden). Creating a Thread
every time may result in an excessive number of concurrent threads.
Short answer, they are all good because you aren't locking the UI.
Longer answer, Mostly comes down to preference. The solution I use is a combination of basic threads and a handler. Since a basic thread does not run on the main UI thread, often when one completes you need to report back or update settings. This is when I use a handler and a set of easy to read keys. Thus allowing me to access any view and change it as needed. Remember, it is unwise to declare and keep global references to Views, allocate and use as needed and discard when done.
private static final int SET_LOADING = 0;
private static final int SET_TEXT = 1;
private Handler mEventHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// if stmts||switch - personal preference
if(msg.what == SET_LOADING ){
setLoading(((Boolean) msg.obj));
}else if(msg.what == SET_TEXT){
setText(msg.arg1, (String) msg.obj);
}
super.handleMessage(msg);
}
}
/**
* set the text of a textbox
* @param id int - R.id.{...}
* @param text String
*/
private void setText(int id, String text){
TextView t = ((TextView) findViewById(id));
if(t != null){
t.setText(text);
}
}
/**
* is the UI currently loading something? lock controls
* @param isLoading boolean
*/
private void setLoading(boolean isLoading){
mIsLoading = isLoading;
if(isLoading){
(SomeSpinningProgressBar).setVisibility(View.VISIBLE);
}else{
(SomeSpinningProgressBar).setVisibility(View.INVISIBLE);
}
}
public void onClick(View v) {
/**
* some button that triggers a database connection
*/
if( v.getId() == R.id.some_button ) {
/** basic thread */
new Thread(new Runnable() {
public void run() {
if(this.hasWebConnection()){
/** tell the UI thread to start loading */
mEventHandler.sendMessage(
mEventHandler.obtainMessage(SET_LOADING, 0, 0, true));
// do work...
if(someErrorOccuredBoolean){
/** report to user of an error */
mEventHandler.sendMessage(
mEventHandler.obtainMessage(SET_TEXT, R.id.some_textview, 0, "There was an error!"));
}
/** tell the UI thread to stop loading */
mEventHandler.sendMessage(
mEventHandler.obtainMessage(SET_LOADING, 0, 0, false));
}else{
mEventHandler.obtainMessage(SET_TEXT, R.id.some_textview, 0, "No internet found!!"));
}
}
}
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With