Android must learn the Asynctask

Source: Internet
Author: User

Asynctask, an asynchronous task, is a class that Android gives us to handle asynchronous tasks. This class enables the UI thread and the background thread to communicate, the background thread executes the asynchronous task, and returns the result to the UI thread.

. Why do I need to use asynchronous tasks?

We know that only the UI thread in Android, the main thread, can perform updates to the UI, while other threads cannot manipulate the UI directly. This is the benefit of ensuring the stability and accuracy of the UI. Avoid UI clutter caused by multiple threads working on the UI at the same time. But Android is a multi-threaded operating system, we can not put all the tasks in the main thread to implement, such as network operation, file read and other time-consuming operations, if all put on the main thread to execute, it may cause the later task blocking . Android detects this blocking and throws a application not responsed (ANR) error when the blocking time is too long. So we need to put these time-consuming operations in a non-main thread to execute. This avoids the single-threaded model of Android, And to avoid the ANR.

. Why is Asynctask born?

When it comes to asynchronous tasks, we can think of threads, thread pools to implement. Indeed, Android gives us the mechanism to communicate with other threads on the main thread. But at the same time, Android also provides us with a packaged component--asynctask. Using Asynctask, We can easily implement asynchronous task processing. Asynctask can update the UI in a child thread, and encapsulation simplifies asynchronous operations. Using threads, the thread pool handles asynchronous tasks involving the synchronization of threads. Management and other issues. And when the thread ends, it needs to use handler to notify the main thread to update the UI. And Asynctask encapsulates all of this so that we can easily update the UI in a child thread.

. Constructing generic parameters for the Asynctask sub-class

Asynctask<params,progress,result> is an abstract class that is typically used for inheritance. The inheritance asynctask needs to specify the following three generic parameters:

Params: The type of parameter entered when the task is started.

Progress: The type of progress value returned in background task execution.

Result: The type of the result returned after the background task execution completes.

. Constructing callback methods for Asynctask subclasses

Asynctask mainly have the following methods:

Doinbackground: You must override the task that executes the background thread asynchronously, and the time-consuming operation is done in this method.

OnPreExecute: Called before a background time-consuming operation is performed, typically for initialization operations.

OnPostExecute: When the Doinbackground method is complete, the system will call this method automatically and pass the value returned by the Doinbackground method to this method. This method is used to update the UI.

Onprogressupdate: This method is called when the Publishprogress method is called in the Doinbackground method to update the progress of the task execution. In this way we can know the progress of the task's completion.

The following code shows an example of a typical asynchronous process-loading a network picture. Network operations, as an unstable time-consuming operation, are prohibited from being placed in the main thread from 4.0 onwards. So when displaying a Web image, we need to download the picture in asynchronous processing and set the picture in the UI thread.

Mainactivity.java

Package Com.example.caobotao.learnasynctask;import Android.app.activity;import Android.content.intent;import Android.os.bundle;import Android.view.view;import Android.view.view.onclicklistener;import Android.widget.Button; public class Mainactivity extends Activity {    private Button btn_image;    @Override    protected void onCreate (Bundle savedinstancestate) {        super.oncreate (savedinstancestate);        Setcontentview (r.layout.activity_main);        Btn_image = (Button) Findviewbyid (r.id.btn_image);        Btn_image.setonclicklistener (New Onclicklistener () {            @Override public            void OnClick (View v) {                StartActivity (New Intent (Mainactivity.this,imageactivity.class));}}        );    }

Imageactivity.java

Package Com.example.caobotao.learnasynctask;import Android.app.activity;import Android.graphics.*;import Android.os.*;import android.view.view;import android.widget.*;import java.io.*;import java.net.*;/** * Created by Caobotao on 15/12/2.    */public class Imageactivity extends Activity {private ImageView ImageView;    Private ProgressBar ProgressBar;    private static String URL = "Http://pic3.zhongsou.com/image/38063b6d7defc892894.jpg";        @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (R.layout.image);        ImageView = (ImageView) Findviewbyid (r.id.image);        ProgressBar = (ProgressBar) Findviewbyid (R.id.progressbar);        Start processing asynchronous tasks by calling the Execute method. Equivalent to the Start method in the thread.    New Myasynctask (). Execute (URL);        } class Myasynctask extends Asynctask<string,void,bitmap> {//onpreexecute is used for operations before asynchronous processing @Override protected void OnPreExecute () {super.onpreexecute ();            The ProgressBar is set to visible here.        Progressbar.setvisibility (view.visible);        }//Processing of asynchronous tasks in the Doinbackground method. @Override protected Bitmap doinbackground (String ... params) {//get passed in parameters String url = params[            0];            Bitmap Bitmap = null;            URLConnection connection;            InputStream is;                try {connection = new URL (URL). OpenConnection ();                is = Connection.getinputstream ();                In order to see more clearly the wait operation to load the picture, the thread sleeps for 3 seconds.                Thread.Sleep (3000);                Bufferedinputstream bis = new Bufferedinputstream (IS);                The input stream is parsed by the Decodestream method bitmap = Bitmapfactory.decodestream (bis);                Is.close ();            Bis.close ();            } catch (IOException e) {e.printstacktrace ();            } catch (Interruptedexception e) {e.printstacktrace ();        } return bitmap;      }  OnPostExecute for UI updates. The parameter for this method is the value returned by the Doinbackground method.            @Override protected void OnPostExecute (Bitmap Bitmap) {super.onpostexecute (BITMAP);            Hidden ProgressBar progressbar.setvisibility (view.gone);        Updated ImageView imageview.setimagebitmap (bitmap); }    }}

Activity_main.xml

<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "              android:orientation=" vertical "              android:layout_width=" match_parent "              android:gravity=" Center "              android:layout_height=" match_parent ">    <button        android:id=" @+id/btn_image "        android:text= "Load Picture"        android:layout_width= "match_parent"        android:layout_height= "Wrap_content"/>   </LinearLayout>

Progress.xml

<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "              android:orientation=" vertical "              android:layout_width=" match_parent "              android:gravity=" Center "              android:layout_height=" match_parent ">    <progressbar        style="? android:attr/ Progressbarstylehorizontal "        android:id=" @+id/progress "        android:layout_width=" Match_parent "        Android : layout_height= "Wrap_content"/></linearlayout>

Because of the network operation involved, you need to add network operation permissions in Androidmanifest.xml: <uses-permission android:name= "Android.permission.INTERNET"/>

Operation Result:

An example of a simulation update progress bar is shown below.

Mainactivity.java

Package Com.example.caobotao.learnasynctask;import Android.app.activity;import Android.content.intent;import Android.os.bundle;import Android.view.view;import Android.view.view.onclicklistener;import Android.widget.Button; public class Mainactivity extends Activity {    private Button btn_progress;    @Override    protected void onCreate (Bundle savedinstancestate) {        super.oncreate (savedinstancestate);        Setcontentview (r.layout.activity_main);        Btn_progress = (Button) Findviewbyid (r.id.btn_progress);        Btn_progress.setonclicklistener (New Onclicklistener () {            @Override public            void OnClick (View v) {                StartActivity (New Intent (Mainactivity.this,progressactivity.class));}}        );    }

Progressactivity.java

Package Com.example.caobotao.learnasynctask;import Android.app.activity;import Android.os.asynctask;import Android.os.asynctask.status;import Android.os.bundle;import Android.widget.progressbar;import java.util.Scanner;/ * * Created by Caobotao on 15/12/2.    */public class Progressactivity extends activity{private ProgressBar ProgressBar;    Private Myasynctask Myasynctask;        @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (r.layout.progress);        ProgressBar = (ProgressBar) Findviewbyid (r.id.progress);        Myasynctask = new Myasynctask ();    Myasynctask.execute (); }
} class Myasynctask extends asynctask<void,integer,void>{@Override protected Void onprogressupdate (Integer ... values) {super.onprogressupdate (values); Update the progress bar with the values passed through the Publishprogress method. Progressbar.setprogress (Values[0]); } @Override protected void Doinbackground (void ... params) {//Use the For loop to simulate the progress of the progress bar. for (int i = 0;i <, i + +) {//Call publishprogress method will automatically trigger the Onprogressupdate method to update the progress bar. Publishprogress (i); try {//through thread hibernation simulates time-consuming operation Thread.Sleep (300); } catch (Interruptedexception e) {e.printstacktrace (); }} return null; } }}

Activity_main.xml

<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "              android:orientation=" vertical "              android:layout_width=" match_parent "              android:gravity=" Center "              android:layout_height=" match_parent ">    <button        android:id=" @+id/btn_progress "        android:text= "Load progress bar"        android:layout_width= "match_parent"        android:layout_height= "Wrap_content"/>< /linearlayout>

Progress.xml

<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "              android:orientation=" vertical "              android:layout_width=" match_parent "              android:gravity=" Center "              android:layout_height=" match_parent ">    <progressbar        style="? android:attr/ Progressbarstylehorizontal "        android:id=" @+id/progress "        android:layout_width=" Match_parent "        Android : layout_height= "Wrap_content"/></linearlayout>

Also need to add network operation permissions in Androidmanifest.xml: <uses-permission android:name= "Android.permission.INTERNET"/>

Operation Result:

After clicking the ' Load progress bar ' button, the program looks normal. However, as shown above, if you click on the Back button and then click the ' Load progress bar ' button again, you will see that the progress bar is always zero, and it will only start updating after a while. Why is this?

According to the above, we know that Asynctask is implemented based on the thread pool, and when a thread does not end, the subsequent thread cannot execute. Therefore, you must wait until the first task's for loop finishes before you can execute the second task. We know that The OnPause () method of the activity is called when the back key is clicked. To solve this problem, we need to mark the executing task as the cancel state in the activity's OnPause () method. When asynchronous processing is performed in the Doinbackground method, it is determined if it is the cancel state to decide whether to cancel the previous task.

Change Progressactivity.java as follows:

Package Com.example.caobotao.learnasynctask;import Android.app.activity;import Android.os.asynctask;import Android.os.asynctask.status;import Android.os.bundle;import Android.widget.progressbar;import java.util.Scanner;/ * * Created by Caobotao on 15/12/2.    */public class Progressactivity extends activity{private ProgressBar ProgressBar;    Private Myasynctask Myasynctask;        @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (r.layout.progress);        ProgressBar = (ProgressBar) Findviewbyid (r.id.progress);        Myasynctask = new Myasynctask ();    Initiates processing of asynchronous tasks Myasynctask.execute ();    //asynctask is implemented based on the thread pool, and when a thread does not end, the subsequent thread is not executed.        @Override protected void OnPause () {super.onpause (); if (myasynctask! = null && myasynctask.getstatus () = = status.running) {//cancel method only marks the corresponding asynctask as can            The Celt state is not a real cancellation thread execution.     Myasynctask.cancel (TRUE);   }} class Myasynctask extends asynctask<void,integer,void>{@Override protected Void Onprogre            Ssupdate (Integer ... values) {super.onprogressupdate (values);            Update the progress bar with the values passed through the Publishprogress method.        Progressbar.setprogress (Values[0]);            } @Override protected void Doinbackground (void ... params) {//Use the For loop to simulate the progress of the progress bar.                for (int i = 0;i <, i + +) {//If the task is a cancel state, the for loop is terminated for execution of the next task.                if (iscancelled ()) {break;                }//Call the Publishprogress method will automatically trigger the Onprogressupdate method to update the progress bar.                Publishprogress (i);                try {//through thread hibernation simulates time-consuming operation Thread.Sleep (300);                } catch (Interruptedexception e) {e.printstacktrace ();        }} return null; }    }}

Precautions for using Asynctask

① must create an instance of Asynctask in the UI thread.

② can only invoke the Execute method of Asynctask in the UI thread.

The four methods that are overridden by the ③asynctask are automatically called by the system and should not be called manually.

④ each asynctask can only be executed (Execute method) at a time, and multiple executions will throw an exception.

⑤asynctask four methods, only the Doinbackground method is run in other threads, the other three methods are running in the UI thread, it is said that the other three methods can be UI update operation.

Android must learn the Asynctask

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.