问题
I got slightly confused about the differences between Handlers
, AsyncTask
and Threads
in Android. I\'ve read quite a few blogs and questions here in StackOverflow.
Handler
are background threads that provide you to communicate with the UI. Updating a progress bar, for instance, should be done via Handler
. Using Handlers you have the advantage of MessagingQueues
, so if you want to schedule messages or update multiple UI elements or have repeating tasks.
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
.
However, I would like to have a socket connection run in service. Should this be run in a handler or a thread, or even an AsyncTask
? UI interaction is not necessary at all. Does it make a difference in terms of performance which I use?
Meanwhile, the documentation has been majorly improved.
回答1:
As the Tutorial on Android background processing with Handlers, AsyncTask and Loaders on the Vogella site puts it:
The Handler
class can be used to register to a thread and provides a simple channel to send data to this thread.
The AsyncTask
class encapsulates the creation of a background process and the synchronization with the main thread. It also supports reporting progress of the running tasks.
And a Thread
is basically the core element of multithreading which a developer can use with the following disadvantage:
If you use Java threads you have to handle the following requirements in your own code:
- Synchronization with the main thread if you post back results to the user interface
- No default for canceling the thread
- No default thread pooling
- No default for handling configuration changes in Android
And regarding the AsyncTask
, as the Android Developer's Reference puts it:
AsyncTask
enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
AsyncTask
is designed to be a helper class aroundThread
andHandler
and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.
Update May 2015: I found an excellent series of lectures covering this topic.
This is the Google Search: Douglas Schmidt lecture android concurrency and synchronisation
This is the video of the first lecture on YouTube
All this is part of the CS 282 (2013): Systems Programming for Android from the Vanderbilt University. Here's the YouTube Playlist
Douglas Schmidt seems to be an excellent lecturer
Important: If you are at a point where you are considering to use AsyncTask
to solve your threading issues, you should first check out ReactiveX/RxAndroid for a possibly more appropriate programming pattern. A very good resource for getting an overview is Learning RxJava 2 for Android by example.
回答2:
If we look at the source code, we will see AsyncTask
and Handler
is purely written in Java. (There are some exceptions, though. But that is not an important point)
So there is no magic in AsyncTask
or Handler
. These classes make our life easier as a developer.
For example: If Program A calls method A(), method A() could run in a different thread with Program A. We can easily verify by following code:
Thread t = Thread.currentThread();
int id = t.getId();
Why should we use a new thread for some tasks? You can google for it. Many many reasons,e.g: lifting heavily, long-running works.
So, what are the differences between Thread
, AsyncTask
, and Handler
?
AsyncTask
and Handler
are written in Java (internally they use a Thread
), so everything we can do with Handler
or AsyncTask
, we can achieve using a Thread
too.
What can Handler
and AsyncTask
really help?
The most obvious reason is communication between the caller thread and the worker thread. (Caller Thread: A thread which calls the Worker Thread to perform some tasks. A caller thread doesn't necessarily have to be the UI thread). Of course, we can communicate between two threads in other ways, but there are many disadvantages (and dangers) because of thread safety.
That is why we should use Handler
and AsyncTask
. These classes do most of the work for us, we only need to know which methods to override.
The difference between Handler
and AsyncTask
is: Use AsyncTask
when Caller thread is a UI Thread.
This is what android document says:
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers
I want to emphasize two points:
1) Easy use of the UI thread (so, use when caller thread is UI Thread).
2) No need to manipulate handlers. (means: You can use Handler instead of AsyncTask, but AsyncTask is an easier option).
There are many things in this post I haven't said yet, for example: what is UI Thread, or why it's easier. You must know some methods behind each class and use it, you will completely understand the reason why.
@: when you read the Android document, you will see:
Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue
This description might seem strange at first. We only need to understand that each thread has each message queue (like a to-do list), and the thread will take each message and do it until the message queue is empty (just like we finish our work and go to bed). So, when Handler
communicates, it just gives a message to caller thread and it will wait to process.
Complicated? Just remember that Handler
can communicate with the caller thread safely.
回答3:
After looking in depth, it's straight forward.
AsyncTask
:
It's a simple way to use a thread without knowing anything about java thread model.
AsyncTask
gives various callbacks respective to the worker thread and main thread.
Use for small waiting operations like the following:
- Fetching some data from web services and display over layout.
- Database query.
- When you realize that running operation will never, ever be nested.
Handler
:
When we install an application in android, then it creates a thread for that application called MAIN UI Thread. All activities run inside that thread. By the android single thread model rule, we can not access UI elements (bitmap , textview etc..) directly for another thread defined inside that activity.
A Handler allows you communicate back with the UI thread from other background thread. This is useful in android as android doesn’t allow other threads to communicate directly with UI thread. Handler can send and process Message and Runnable objects associated with a thread’s MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue. When a new Handler is created, it is bound to the thread/message queue of the thread that is creating it.
It's the best fit for:
- It allows you to do message queuing.
- Message scheduling.
Thread
:
Now it's time to talk about thread.
Thread is the parent of both AsyncTask
and Handler
. They both internally use thread, which means you can also create your own thread model like AsyncTask
and Handler
, but that requires a good knowledge of Java's Multi-Threading Implementation.
回答4:
An AsyncTask
is used to do some background computation and publish the result to the UI thread (with optional progress updates). Since you're not concerned with UI, then a Handler
or Thread
seems more appropriate.
You can spawn a background Thread
and pass messages back to your main thread by using the Handler
's post
method.
回答5:
Thread
Android supports standard Java Threads. You can use standard Threads and the tools from the package “java.util.concurrent
” to put actions into the background. The only limitation is that you cannot directly update the UI from the a background process.
If you need to update the UI from a background task you need to use some Android specific classes. You can use the class “android.os.Handler
” for this or the class “AsyncTask
”
Handler
The class “Handler
” can update the UI. A handle provides methods for receiving messages and for runnables. To use a handler you have to subclass it and override handleMessage()
to process messages. To process Runable
, you can use the method post();
You only need one instance of a handler in your activity.
You thread can post messages via the method sendMessage(Message msg)
or sendEmptyMessage
.
AsyncTask
If you have an Activity
which needs to download content or perform operations that can be done in the background AsyncTask
allows you to maintain a responsive user interface and publish progress for those operations to the user.
For more information you can have a look at these links.
http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/
http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask
回答6:
Thread
:
You can use new Thread
for long running background tasks without impacting UI Thread. From java Thread, you can't update UI Thread.
Since normal Thread is not much useful for Android architecture, helper classes for threading have been introduced.
You can find answers to your queries in Threading performance documentation page.
Handler:
A Handler
allows you to send and process Message and Runnable
objects associated with a thread's MessageQueue
. Each Handler
instance is associated with a single thread and that thread's message queue.
There are two main uses for a Handler
:
To schedule messages and runnables to be executed as some point in the future;
To enqueue an action to be performed on a different thread than your own.
AsyncTask:
AsyncTask
enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
Drawbacks:
By default, an app pushes all of the
AsyncTask
objects it creates into a single thread. Therefore, they execute in serial fashion, and—as with the main thread—an especially long work packet can block the queue. Due to this reason, use AsyncTask to handle work items shorter than 5ms in duration.AsyncTask
objects are also the most common offenders for implicit-reference issues.AsyncTask
objects present risks related to explicit references, as well.
HandlerThread:
You may need a more traditional approach to executing a block of work on a longer running thread (unlike AsyncTask, which should be used for 5ms workload) , and some ability to manage that workflow manually. A handler thread is effectively a long-running thread that grabs work from a queue, and operates on it.
ThreadPoolExecutor:
This class manages the creation of a group of threads, sets their priorities, and manages how work is distributed among those threads. As workload increases or decreases, the class spins up or destroys more threads to adjust to the workload.
If workload is more and single HandlerThread
is not suffice, you can go for ThreadPoolExecutor
However I would like to have a socket connection run in a service. Should this be run in a handler or a thread, or even an AsyncTask? UI interaction is not necessary at all. Does it make a difference in terms of performance which I use?
Since UI interaction is not required, you may not go for AsyncTask
. Normal threads are not much useful and hence HandlerThread
is best option. Since you have to maintain socket connection, Handler on main thread is not useful at all. Create a HandlerThread
and get a Handler
from looper of HandlerThread
.
HandlerThread handlerThread = new HandlerThread("SocketOperation");
handlerThread.start();
Handler requestHandler = new Handler(handlerThread.getLooper());
requestHandler.post(myRunnable); // where myRunnable is your Runnable object.
If you want to communicate back to UI thread, you can use one more Handler to process response.
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Foreground task is completed:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
in your Runnable
, you can add
responseHandler.sendMessage(msg);
More details about implementation can be found here:
Android: Toast in a thread
回答7:
In my opinion threads aren't the most efficient way of doing socket connections but they do provide the most functionality in terms of running threads. I say that because from experience, running threads for a long time causes devices to be very hot and resource intensive. Even a simple while(true)
will heat a phone in minutes. If you say that UI interaction is not important, perhaps an AsyncTask
is good because they are designed for long-term processes. This is just my opinion on it.
UPDATE
Please disregard my above answer! I answered this question back in 2011 when I was far less experienced in Android than I am now. My answer above is misleading and is considered wrong. I'm leaving it there because many people commented on it below correcting me, and I've learned my lesson.
There are far better other answers on this thread, but I will at least give me more proper answer. There is nothing wrong with using a regular Java Thread
; however, you should really be careful about how you implement it because doing it wrong can be very processor intensive (most notable symptom can be your device heating up). AsyncTask
s are pretty ideal for most tasks that you want to run in the background (common examples are disk I/O, network calls, and database calls). However, AsyncTask
s shouldn't be used for particularly long processes that may need to continue after the user has closed your app or put their device to standby. I would say for most cases, anything that doesn't belong in the UI thread, can be taken care of in an AsyncTask
.
回答8:
AsyncTask
is designed to perform not more than few seconds operation to be done in background (not recommended for megabytes of file downloading from server or compute cpu intensive task such as file IO operations ). If you need to execute a long running operation, you have been strongly advised to use java native threads. Java gives you various thread related classes to do what you need. Use Handler
to update the UI Thread.
回答9:
public class RequestHandler {
public String sendPostRequest(String requestURL,
HashMap<String, String> postDataParams) {
URL url;
StringBuilder sb = new StringBuilder();
try {
url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode = conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
sb = new StringBuilder();
String response;
while ((response = br.readLine()) != null){
sb.append(response);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for (Map.Entry<String, String> entry : params.entrySet()) {
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}
}
回答10:
Let me try and answer the question here with an example :) - MyImageSearch [Kindly refer the image here of the main activity screen - containing an edit text / search button / grid view]
Description of MyImageSearch - Once user enters the details on the edit text field and clicks on the search button, we will search images on the internet via the web services provided by flickr (you only need to register there to get a key/secret token) - for searching we send an HTTP Request and GET JSON Data back in response containing the url's of individual images which we will then use to load the grid view.
My Implementation - In the main activity I will define a inner class which extends the AsyncTask to send the HTTP Request in doInBackGround Method and fetch the JSON Response and update my local ArrayList of FlickrItems which I am going to use to update my GridView via the FlickrAdapter (extends the BaseAdapter) and call the adapter.notifyDataSetChanged() in the onPostExecute() of AsyncTask to reload the grid view. Note that here the HTTP Request is a blocking call because of which I have done it via the AsyncTask. And, I can cache the items in adapter to increase the performance or store them on SDCard. The grid that I will be inflating in the FlickrAdapter contains in my implementation a progressbar and image view. Below you can find the code for mainActivity which I used.
Answer to the Question Now - So once we have the JSON data for fetching individual Images we can implement the logic of getting the images in background via Handlers or Threads or AsyncTask. We should note here that since my images once downloaded must be displayed on the UI/main thread we cannot simply use threads as it is since they don't have access to the context. In the FlickrAdapter, the choices I could think of:
- Choice 1: Create a LooperThread [extends thread] - and keep on downloading images sequentially in one thread by keeping this thread open [looper.loop()]
- Choice 2: Make use of a Thread Pool and post the runnable via myHandler which contains reference to my ImageView, but since the views in Grid View are recycled, again the problem might arise where image at index 4 is displayed at index 9 [download may take more time]
- Choice 3 [I used this]: Make use of a Thread Pool and send a message to myHandler, which contains data related to ImageView's index and ImageView itself, so while doing handleMessage() we will update the ImageView only if currentIndex matches the index of the Image we tried to download.
- Choice 4: Make use of AsyncTask to download the images in background, but here I will not have access to the number of threads I want in the thread pool and it varies with different android version, but in Choice 3 I can make of conscious decision of the size of thread pool depending on device configuration being used.
Here the source code:
public class MainActivity extends ActionBarActivity {
GridView imageGridView;
ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
FlickrAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageGridView = (GridView) findViewById(R.id.gridView1);
adapter = new FlickrAdapter(this, items);
imageGridView.setAdapter(adapter);
}
// To avoid a memory leak on configuration change making it a inner class
class FlickrDownloader extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
FlickrGetter getter = new FlickrGetter();
ArrayList<FlickrItem> newItems = getter.fetchItems();
// clear the existing array
items.clear();
// add the new items to the array
items.addAll(newItems);
// is this correct ? - Wrong rebuilding the list view and should not be done in background
//adapter.notifyDataSetChanged();
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
adapter.notifyDataSetChanged();
}
}
public void search(View view) {
// get the flickr data
FlickrDownloader downloader = new FlickrDownloader();
downloader.execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I hope my answer though long will help in understanding some of the finer details.
回答11:
It depends which one to chose is based on the requirement
Handler is mostly used to switch from other thread to main thread, Handler is attached to a looper on which it post its runnable task in queue. So If you are already in other thread and switch to main thread then you need handle instead of async task or other thread
If Handler created in other than main thread which is not a looper is will not give error as handle is created the thread, that thread need to be made a lopper
AsyncTask is used to execute code for few seconds which run on background thread and gives its result to main thread ** *AsyncTask Limitations 1. Async Task is not attached to life cycle of activity and it keeps run even if its activity destroyed whereas loader doesn't have this limitation 2. All Async Tasks share the same background thread for execution which also impact the app performance
Thread is used in app for background work also but it doesn't have any call back on main thread. If requirement suits some threads instead of one thread and which need to give task many times then thread pool executor is better option.Eg Requirement of Image loading from multiple url like glide.
回答12:
Handler
- is communication medium between threads. In android it is mostly used to communicate with main thread by creating and sending messages through handler
AsyncTask
- is used to perform long running applications in a background thread. With nAsyncTask
you get can do the operation in a background thread and get the result in the main thread of the application.
Thread
- is a light weight process, to achieve concurrency and maximum cpu utilization. In android you can use thread to perform activities which does not touch UI of the app
回答13:
Thread
When you start an app, a process is created to execute the code. To efficiently use computing resource, threads can be started within the process so that multiple tasks can be executed at the time. So threads allow you to build efficient apps by utilizing cpu efficiently without idle time.
In Android, all components execute on a single called main thread. Android system queue tasks and execute them one by one on the main thread. When long running tasks are executed, app become unresponsive.
To prevent this, you can create worker threads and run background or long running tasks.
Handler
Since android uses single thread model, UI components are created non-thread safe meaning only the thread it created should access them that means UI component should be updated on main thread only. As UI component run on the main thread, tasks which run on worker threads can not modify UI components. This is where Handler comes into picture. Handler with the help of Looper can connect to new thread or existing thread and run code it contains on the connected thread.
Handler makes it possible for inter thread communication. Using Handler, background thread can send results to it and the handler which is connected to main thread can update the UI components on the main thread.
AsyncTask
AsyncTask provided by android uses both thread and handler to make running simple tasks in the background and updating results from background thread to main thread easy.
Please see android thread, handler, asynctask and thread pools for examples.
来源:https://stackoverflow.com/questions/6964011/handler-vs-asynctask-vs-thread