Summary:
In the development of Android mobile client, multi-threading is often used to operate. We usually put time-consuming operations into separate threads to execute, so as to avoid occupying the main threads and bring bad user experience to users. However, it is impossible to operate the main thread (UI thread) in the sub-thread, and there will be errors in the operation of the UI thread in the sub-thread. Therefore, Android provides a Handler class to update UI threads in sub-threads, and update UI interfaces with messaging mechanism to present to users. This solves the problem of sub-threads updating the UI. But time-consuming task operations always start some anonymous sub-threads. Too many sub-threads impose a huge burden on the system, resulting in some performance problems. So Android provides a tool class, AsyncTask, to perform tasks asynchronously as the name implies. This AsyncTask was born to deal with some time-consuming tasks in the background, bringing users a good user experience. It is graceful in programming grammar. It can complete asynchronous operations and refresh the user interface without requiring sub-threads and handlers. Let's start with an overview of the Android.os.AsyncTask class: * The android class AsyncTask wraps the inter-thread communication and provides a simple programming way for background threads to communicate with UI threads: background threads perform asynchronous tasks and notify UI threads of the results of operations. * AsyncTask is an abstract class. AsyncTask defines three generic types Params, Progress and Result.
* Params starts the input parameters for task execution, such as the URL of the HTTP request.
* Percentage of background task execution for Progress.
* Result background execution tasks eventually return results, such as String,Integer and so on.
* The implementation of AsyncTask is divided into four steps, each corresponding to a callback method, which developers need to implement.
* 1) Inheritance of AsyncTask
* 2) Implement one or more of the following methods defined in AsyncTask
* onPreExecute(), which is called by the UI thread before the actual background operation is performed. Some preparatory work can be done in this method, such as displaying a progress bar on the interface, or instantiating some controls. This method can not be implemented.
* doInBackground(Params... The onPreExecute method, which runs in the background thread, is executed immediately after the onPreExecute method is executed. The main responsibility here will be to perform those time-consuming background processing tasks. The publishProgress method can be called to update the real-time task schedule. This method is abstract and subclasses must be implemented.
* onProgress Update After the publishProgress method is invoked, the UI thread will invoke the method to show the progress of the task on the interface, such as through a progress bar.
* onPostExecute(Result), after the doInBackground execution is completed, the onPostExecute method will be called by the UI thread, and the background calculation results will be passed to the UI thread through this method, and displayed to the user on the interface.
* onCancelled(), which is called when the user cancels the thread operation. Called when onCancelled() is called in the main thread.
In order to use the AsyncTask class correctly, the following guidelines must be followed:
1) Task instances must be created in UI threads
2) The execute method must be invoked in the UI thread
3) Do not manually call onPreExecute(), onPostExecute(Result), doInBackground(Params... ) onProgress Update ) These methods need to be invoked by instantiating the task in the UI thread.
4) The task can only be executed once, otherwise an exception will occur when multiple calls are made.
The parameters of the doInBackground method and onPostExecute must correspond. These two parameters are specified in the generic parameter list declared by AsyncTask. The first parameter is accepted by doInBackground, the second is the parameter showing progress, and the third is the parameter returned by doInBackground and passed in by onPostExecute.
The parameter type of AsyncTask<> is set by the user, and here it is set to three String.
- The first String represents the parameter type entered into the task, that is, the parameter type of doInBackground().
The second String represents the parameter type in the processing, that is, the output parameter type in the execution of doInBackground(), and sends messages through publishProgress().
Passing to onProgressUpdate() is generally used to update the interface
- The third String represents the output type at the end of the task, that is, the return value type of doInBackground(), and the parameter type of onPostExecute().
private class task extends AsyncTask
public class NetworkActivity extends Activity{
private TextView message;
private Button open;
private EditText url;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.network);
message= (TextView) findViewById(R.id.message);
url= (EditText) findViewById(R.id.url);
open= (Button) findViewById(R.id.open);
open.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
connect();
}
});
}
private void connect() {
PageTask task = new PageTask(this);
task.execute(url.getText().toString());
}
class PageTask extends AsyncTask<String, Integer, String> {
// Variable length input parameter corresponding to AsyncTask.exucute()
ProgressDialog pdialog;
public PageTask(Context context){
pdialog = new ProgressDialog(context, 0);
pdialog.setButton("cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int i) {
dialog.cancel();
}
});
pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
finish();
}
});
pdialog.setCancelable(true);
pdialog.setMax(100);
pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pdialog.show();
}
@Override
protected String doInBackground(String... params) {
try{
HttpClient client = new DefaultHttpClient();
// params[0] represents the url of the connection
HttpGet get = new HttpGet(params[0]);
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
long length = entity.getContentLength();
InputStream is = entity.getContent();
String s = null;
if(is != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[128];
int ch = -1;
int count = 0;
while((ch = is.read(buf)) != -1) {
baos.write(buf, 0, ch);
count += ch;
if(length > 0) {
// If you know the length of the response, call publishProgress () to update the progress
publishProgress((int) ((count / (float) length) * 100));
}
// Let threads sleep for 100 ms
Thread.sleep(100);
}
s = new String(baos.toByteArray()); }
// Return result
return s;
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onCancelled() {
super.onCancelled();
}
@Override
protected void onPostExecute(String result) {
// Return the content of the HTML page
message.setText(result);
pdialog.dismiss();
}
@Override
protected void onPreExecute() {
// Task startup, you can display a dialog box here, here simple processing
message.setText(R.string.task_started);
}
@Override
protected void onProgressUpdate(Integer... values) {
// Update progress
System.out.println(""+values[0]);
message.setText(""+values[0]);
pdialog.setProgress(values[0]);
}
}