Android multithreading-AsyncTask asynchronous task

【statement】

Welcome to reprint, but please keep the original source of the article → _ →

Life One: http://www.cnblogs.com/smyhvae/

Article source: http://www.cnblogs.com/smyhvae/p/3866570.html

 

【text】

This article will explain the knowledge of Android multi-threading, and how to achieve communication between threads through the AsyncTask mechanism.

1. Multithreading in Android:

In Android, when an application component starts, and no other application components are running, the Android system will open a new thread for the application component to execute. By default, in the same Android application, the components inside are all running in the same thread, this thread is called the Main thread. When we start another component through a certain component, this time is completed in the same thread by default. Of course, we can manage the threads of our Android application ourselves, and we can create additional threads for the application according to our own needs.

二、Main Thread 和 Worker Thread:

In Android, threads are usually divided into two types, one is called Main Thread, and all threads except Main Thread can be called Worker Thread.

When an application is running, the Android operating system will start a thread for the application. This thread is our Main Thread. This thread is very important. It is mainly used to load the UI interface and complete the interaction between the system and the user. , And show the result after interaction to the user, so Main Thread is also called UI Thread.

The Android system does not create an additional thread for application components by default. All these components run in the same thread by default. However, sometimes when our application needs to complete a time-consuming operation (such as accessing the network or querying the database), the UI Thread will be blocked at this time. For example, when we click on a Button and then want it to get some data from the network, if this operation is completed in the UI Thread, the UI thread will be in a blocked state. At this time, our system will not dispatch any other events. Even worse, if our entire site is blocked for more than 5 seconds (official description), the famous ANR (Application Not Responding) problem will appear at this time. At this time, the application will pop up a box to let The user chooses whether to exit the program. For Android development, the phenomenon of ANR is absolutely not allowed.

In addition, because Android UI controls are not thread-safe, we cannot operate UI controls in threads other than UI Thread. Therefore, in the multithreaded programming of Android, there are two very important principles that must be observed:

  • Can not perform time-consuming operations in UI Thread, so as not to block UI Thread
  • Cannot manipulate UI elements in threads other than UI Thread

 Third, how to handle the communication between UI Thread and Worker Thread:

We can neither handle time-consuming operations in the main thread, nor access our UI controls in the worker thread. So, if we want to download an image from the network, how can we update it to the UI control? This is related to the communication between the main thread and the worker thread. In Android, two methods of asynchronous message processing mechanism are provided to solve the communication problem between threads, one is through the Handler mechanism (this method will be described in detail in the following blog), and the other is today. A detailed explanation of the AsyncTask mechanism.

Four, AsyncTask:

AsyncTask: Asynchronous task, literally, is to complete some operations asynchronously while the main UI thread is running. AsyncTask allows us to perform an asynchronous task in the background. We can put time-consuming operations in asynchronous tasks to execute, and return the results of task execution to the UI thread at any time to update UI controls. Through AsyncTask we can easily solve the communication problem between multiple threads.

How to understand AsyncTask? Generally speaking, AsyncTask is equivalent to Android providing us with a framework for multi-threaded programming, which is between Thread and Handler. If we want to define an AsyncTask, we need to define a class to inherit the abstract class AsyncTask, and Implement its only doInBackgroud abstract method.

To master AsyncTask, we must have a concept, summed up as follows: 3 generics, 4 steps.

Let's take a look at the definition of the AsyncTask abstract class. When we define a class to inherit the AsyncTask class, we need to specify three generic parameters for it:

AsyncTask <Params, Progress, Result>
  • Params : specifies the type of parameters we pass to the asynchronous task when it is executed
  • Progress : specifies the type of parameters that our asynchronous task returns to the UI thread when the asynchronous task is executed
  • Result : Specifies the type of result returned to the UI thread after the asynchronous task is executed

 When we define a class that inherits the AsyncTask class, we must specify these three generic types, if not specified, they will be written as Void, for example:

AsyncTask <Void, Void, Void>

4 steps: When we execute an asynchronous task, we need to perform the following 4 steps:

  • onPreExecute ():  This method is executed before the asynchronous task is executed, and is executed in the UI Thread, usually we do some initialization operations of UI controls in this method, such as popping ProgressDialog
  • doInBackground (Params ... params):  This method will be executed immediately after the onPreExecute () method is executed. This method is to handle asynchronous tasks. The Android operating system will start a worker thread in the background thread pool to execute This method (that is, executed in the worker thread), after execution, sends the execution result to the last onPostExecute method. In this method, we can obtain data from the network and other time-consuming operations
  • onProgressUpdate (Progess ... values):  This method is also executed in the UI Thread. When the asynchronous task is executed, sometimes it is necessary to return the progress of the execution to the UI interface. For example, to download a network image, we need to display its download at all times. You can use this method to update the progress. Before this method is called, we need to call a publishProgress (Progress) method in the doInBackground method to pass the progress to the onProgressUpdate method every moment to update
  • onPostExecute (Result ... result):  After the asynchronous task is executed, the result will be returned to this method, this method is also called in the UI Thread, we can display the returned result on the UI control

 Why does the AsyncTask abstract class have only one abstract method of doInBackground? ? The reason is that if we want to do an asynchronous task, we must open up a new Thread for it to complete some operations, and when completing this asynchronous task, I may not need to pop up the ProgressDialog, and do not need to update the ProgressDialog at any time The progress bar does not need to update the results to the UI interface, so all three methods except the doInBackground method are not necessary, so the method that must be implemented is the doInBackground method.

The four-step concise version is described as follows:

  Step 1: Represent the operation before the task is executed

  Step 2: Mainly complete time-consuming operations

  The third step: mainly to update the UI operation

  Step four: produce the final result

The meanings represented in the following examples are:

  Step 1: Display the progress bar

  Step 2: (This task is essential) Perform the task in the background, pass the progress value to the third step, and pass the result to the fourth step;

  Step 3: Update progress value

  Step four: produce the final result

 

5. [Example] Download a picture from the Internet through AsyncTask:

Here are two code examples to see how to download an image from the Internet through AsyncTask and update it to the ImageView control.

Prior to this, the operation must be performed: add network authorization. The following example will have a detailed operation description.

[Example 1] Download a picture from the network, a ProgressDialog pops up, but the real-time progress is not displayed:

1. Add network authorization:

Because the phone cannot access the network by default, first add the network authorization in the manifest file AndroidManifest.xml.

Methods as below:

Open the AndroidManifest.xml file, click the "Permissions" button, and then click "Add":

clip_image002_thumb[1]

After the dialog box pops up, select the last item: Users Permission:

clip_image003_thumb[4]

Then select the Internet option:

clip_image004_thumb[3]

Press Ctrl + S to save.

Next, we can see the corresponding automatically generated code in the manifest file:

clip_image005_thumb[1]

 

In fact, it is also possible to add this line of code directly in the AndroidManifest.xml file.

2. The full version code is as follows:

The code of activity_main.xml:

Copy code

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="136dp"
        android:text="下载网络图片" />
</RelativeLayout>

Copy code

Code of MainActivity.java:

Copy code

package com.example.downloadimage01;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends Activity { 
    private ImageView imageView; 
    private Button button;    
    private ProgressDialog dialog; 
    // picture from the network 
    private String image_path = "http://imgsrc.baidu.com/forum/pic/item/7c1ed21b0ef41bd51a5ac36451da81cb39db3d10.jpg"; 
    @Override 
    protected void onCreate (Bundle savedInstanceState) { 
        super.onCreate (savedInstanceState); 
        setContentView (R.layout.activity_main); 
        
        // Add a pop-up dialog 
        dialog = new ProgressDialog (this); 
        dialog.setTitle ("prompt"); 
        dialog.setMessage ("Downloading image, please wait ...");
        
        imageView = (ImageView) findViewById (R.id.imageView1); 
        button = (Button) findViewById (R.id.button1); 
        button.setOnClickListener (new 
            
            OnClickListener () { @Override 
            public void onClick (View v) { 
            // click When the button is pressed, the operation of performing an asynchronous task 
                new DownTask (). Execute (image_path); 
            } 
        }); // Note that the semicolon in this place is easy to forget 
    } 
    / * 
     * Asynchronous task execution network downloads pictures 
     * * / 
    public class DownTask extends AsyncTask <String, Void, Bitmap> { 
    // In the above method, the first parameter: the path of the network image, the second parameter of the packaging class: the scale of the progress, the third parameter: the return result of the task execution 
        @Override 
        // Show progress bar on the interface
        protected void onPreExecute () { 
            dialog.show (); 
        }; 
                    byte [] data = EntityUtils.toByteArray (httpEntity); 
        protected BitmapdoInBackground (String ... params) {// Three points, representing variable parameters 
            // Use the network link class HttpClient class to complete the extraction of network data 
            HttpClient httpClient = new DefaultHttpClient (); 
            HttpGet httpget = new HttpGet (params [0 ]); 
            Bitmap bitmap = null; 
            try { 
                HttpResponse httpResponse = httpClient.execute (httpget); 
                if (httpResponse.getStatusLine (). 
                    GetStatusCode () == 200) { HttpEntity httpEntity = httpResponse.getEntity (); 
                    bitmap = BitmapFactory.decodeByteArray (data, 0, data.length); 
                } 
            } catch (Exception e) { 
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return bitmap;
        }
            //主要是更新UI
            @Override
            protected void onPostExecute(Bitmap result) { 
                super.onPostExecute(result);
                imageView.setImageBitmap(result) ;//更新UI
                dialog.dismiss() ;                
            }        
    }
    @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;
    }
    
}

Copy code

After running, click the button, the results are as follows: 
clip_image006_thumb[3]clip_image007_thumb[3]

 

 [Example 2] Download a picture from the network, and a dialog box that displays the progress value will pop up:

Note: Since the progress value is to be displayed, the style of the progress bar here should be set to horizontal.

1. Add network authorization (same as above)

2. The full version code is as follows:

The code of activity_main.xml is the same as in [Example 1];

Code of MainActivity.java:

Copy code

  1 package com.example.smyh001downloadimage01;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.InputStream;
  5 
  6 import org.apache.http.HttpEntity;
  7 import org.apache.http.HttpResponse;
  8 import org.apache.http.client.HttpClient;
  9 import org.apache.http.client.methods.HttpGet;
 10 import org.apache.http.impl.client.DefaultHttpClient;
 11 
 12 import android.app.Activity;
 13 import android.app.ProgressDialog;
 14 import android.graphics.Bitmap;
 15 import android.graphics.BitmapFactory;
 16 import android.os.AsyncTask;
 17 import android.os.Bundle;
 18 import android.view.Menu;
 19 import android.view.View;
 20 import android.view.View.OnClickListener;
 21 import android.widget.Button;
 22 import android.widget.ImageView;
 23 
 24 public class MainActivity extends Activity {
 25 
 26     private ImageView imageView ;
 27     private Button button ;   
 28     private ProgressDialog dialog ;
 29     //来自网络的图片
 30     private String image_path = "http://imgsrc.baidu.com/forum/pic/item/7c1ed21b0ef41bd51a5ac36451da81cb39db3d10.jpg" ;
 31     @Override
 32     protected void onCreate(Bundle savedInstanceState) {
 33         super.onCreate(savedInstanceState);
 34         setContentView(R.layout.activity_main);
 35          
 36 // Add popup dialog 
 37 dialog = new ProgressDialog (this); 
 38 dialog.setTitle ("prompt"); 
 39 dialog.setMessage ("Downloading picture, please wait ..."); 
 40 // Set the progress bar to a horizontal style so that it can display the specific progress value 
 41 dialog.setProgressStyle (ProgressDialog.STYLE_HORIZONTAL); 
 42 dialog.setCancelable (false); // After using this method, the progress bar is not until the image download is completed Will disappear (even before the screen is clicked) 
 43          
 44 imageView = (ImageView) findViewById (R.id.imageView1); 
 45 button = (Button) findViewById (R.id.button1); 
 46 button.setOnClickListener (new OnClickListener ( ) { 
 47              
 48 @Override 
 49 public void onClick (View v) {
 50 // When the button is clicked, the asynchronous task is executed 
 51 new DownTask (). Execute (image_path); 
 52} 
 53}); // Note that the semicolon in this place is easy to forget 
 54 
 55}     
 56 
 57 
 58 / * 
 59 * Asynchronous task execution network download pictures 
 60 * * / 
 61 public class DownTask extends AsyncTask <String, Integer, byte []> { 
 62 // In the above method, the first parameter: the path of the network image, the packaging of the second parameter Class: scale of progress, third parameter: return result of task execution 
 63 @Override 
 64 // Display progress bar on the interface 
 65 protected void onPreExecute () { 
 66 dialog.show (); 
 67}; 
 68 
 69 protected byte [ ] doInBackground (String ... params) {// Three points, representing variable parameters
 70 // Use the network link class HttpClient class to complete the extraction of network data, that is, to complete the download function of the image 
 71 HttpClient httpClient = new DefaultHttpClient (); 
 72 HttpGet httpget = new HttpGet (params [0]); 
 73 byte [] result = null; 
 74 ByteArrayOutputStream outputStream = new ByteArrayOutputStream (); 
 75 InputStream inputStream = null; 
 76              
 77 try { 
 78 HttpResponse httpResponse = httpClient.execute (httpget); 
 79 if (httpResponse.getStatusLine (). getStatusCode () == 200) { 
 80                      
 81 HttpEntity httpEntiry = httpResponse.getEntity ();
 82 inputStream = httpEntiry.getContent (); 
 83 // first get the total length of the file 
 84 long file_length = httpResponse.getEntity (). GetContentLength (); 
 85 int len ​​= 0; 
 86 // read 1024 bytes each time 
 87 byte [] data = new byte [1024];   
 88 // The accumulated length after each reading 
 89 int total_length = 0;           
 90 while ((len = inputStream.read (data))! =-1) { 
 91 / / Each time it is read, the total_length is added up 
 92 total_length + = len; 
 93 // Get the current picture download progress
 94 int progress_value = (int) ((total_length / (float) file_length) * 100); 
 95 // always update the current progress to the onProgressUpdate method 
 96 publishProgress (progress_value); 
 97 outputStream.write (data, 0, len); 
 98 } 
 99 // Write to ByteArrayOutputStream while reading 
100 result = outputStream.toByteArray (); 
101 // bitmap = BitmapFactory.decodeByteArray (result, 0, result.length); 
102} 
103} catch (Exception e) { 
104 / / TODO Auto-generated catch block 
105 e.printStackTrace ();
106             } finally {
107                 httpClient.getConnectionManager().shutdown();
108             }
109             return result;
110         }
111             
112         @Override
113         protected void onProgressUpdate(Integer... values) {
114             // TODO Auto-generated method stub
115             super.onProgressUpdate(values);
116             //    更新ProgressDialog的进度条
117             dialog.setProgress(values[0]);
118         }
119         
120         //主要是更新UI        
121         @Override
122         protected void onPostExecute(byte[] result) { 
123 super.onPostExecute (result); 
124 // Decode the byte [] returned by the doInBackground method to Bitmap 
125 Bitmap bitmap = BitmapFactory.decodeByteArray (result, 0, result.length); 
126 // Update our ImageView control 
127 imageView.setImageBitmap (bitmap); // Update UI 
128 // Make ProgressDialog box disappear 
129 dialog.dismiss ();     
130}         
131} 
132 
133 @Override 
134 public boolean onCreateOptionsMenu (Menu menu) { 
135 // Inflate the menu; this adds items to the action bar if it is present. 
136 getMenuInflater (). inflate (R.menu.main, menu); 
137 return true;
138     }
139     
140 }

Copy code

 

After running, the results are as follows:

  

【Project Files】

Link: http://pan.baidu.com/s/1dDvhXkt

Password: 47ce

 

6. Important knowledge points of AsyncTask:

After understanding the working principle of AsyncTask, continue to add some other knowledge points of AsyncTask:

1、Cancelling a Task

We can cancel the execution of the asynchronous task at any time by calling the cancel (boolean) method. After calling this method, the system will then call the isCancelled () method and return true. If this method is called, after the doInBackgroud () method is executed, the onPostExecute () method will not be called, and the onCancelled () method will be called instead. If necessary, in order to ensure that the Task has been canceled, we often need to call the isCancelled () method to judge.

2. The principles that must be followed when using AsyncTask for asynchronous tasks:

  • The AsyncTask class must be loaded in the UI Thread, which is done automatically after the Android Jelly_Bean version
  • AsyncTask objects must be instantiated in UI Thread
  • execute method must be called in UI Thread
  • Do not manually call the four methods of AsyncTask, these are automatically called by the Android system
  • AsyncTask task can only be executed once

 

【to sum up】

So far, the summary about AsyncTask is over. This article mainly explains the knowledge of multithreading in Android, and explains the concept and implementation mechanism of AsyncTask asynchronous tasks in detail, and understands the execution process of AsyncTask through examples. Added some important knowledge points of AsyncTask, including how to cancel an AsyncTask and the rules that must be followed when using AsyncTask. It is recommended that beginners (including me) can refer to the official API documentation when understanding this issue.

Published 10 original articles · Like 11 · Visits 20,000+

Guess you like

Origin blog.csdn.net/u013323018/article/details/83215359