Practical Android skills: in-depth analysis of asynctask)

Source: Internet
Author: User

Http://blog.csdn.net/hitlion2008/article/details/7983449

Introduction and basic usage of asynctask

For the introduction and basic usage of asynctask, refer to the official documentation and practical Android skills: multi-threaded asynctask.

A problem caused by asynctask

Last week, I encountered an extremely strange problem. A small function downloads an image from the network and puts it in the imageview. It is implemented using asynctask, and its logic is also very simple, only extract the input stream of the image with an HTTP request in doinbackground, parse it with bitmapfactory, and then put the obtained bitmap in imageview. This application is developed with the SDK of 4.0 and runs on the SDK of 4.0. However, sometimes it takes a long time to download this image, or even a few minutes. Debugging finds an unacceptable fact: It turns out that doinbackground () is not executed in time, that is, it is not executed immediately after # execute () is called, it takes a long time for execution.

Is asynctask not a thread or an asynchronous asynctask?

Asynctask

Asynctask consists of two parts: one is the interaction with the main line, and the other is the management and scheduling of threads. Although there may be multiple asynctask sub-class instances, the internal handler and threadpoolexecutor of asynctask are shared within the process scope, and they are static, that is, they belong to the class, the scope of the class attribute is classpath. Because a process is a VM, asynctask controls all subclass instances within the process range.

Interaction with the main thread

Handler is used to interact with the main thread. This article mainly discusses the task scheduling of asynctask, so I will not elaborate on this part. If you are interested, you can check the source code of asynctask.

 

Scheduling of thread tasks

Internally, a thread pool in the process scope will be created to manage the tasks to run. That is to say, after you call asynctask # execute (), asynctask will hand over the tasks to the thread pool, the thread pool is used to manage thread creation and running therad. Different Android versions of the internal thread pool are implemented in different ways:

Previous versions of android2.3, that is, SDK/API 10 and earlier versions

The internal thread pool is limited to five, that is to say, there can be only five threads running at the same time. The threads exceeding the limit can only wait, and will be scheduled and run only after a previous thread is executed. In other words, if the number of asynctask instances in a process exceeds 5, then if the first five instances run for a long time, the first 6th instances can only wait for the opportunity. This is a limitation of asynctask and cannot be solved for versions earlier than 2.3. If your application requires a large number of background threads to execute tasks, you can only discard the use of asynctask, create a thread pool by yourself to manage the thread, or simply use the thread pool directly without the thread pool. I have to say that although asynctask is easier to use than thread, it can only run up to five threads at the same time, which greatly limits its strength, you must carefully design your application, stagger the time used for asynctask, and try your best to achieve time-sharing, or ensure that the number is no greater than five. Otherwise, you may encounter the problems mentioned above. Otherwise, you can only use the API in javase.


Android 3.0 and later versions, that is, SDK/API 11 and later versions

Probably because Google realized the limitations of asynctask, and made some adjustments to the asynctask API from Android 3.0:

  1. # Execute (): Only one task is run in sequence.

    That is to say, it is in the order of submission. Each time only one thread is started to execute one task, and then the second task is executed after completion, that is, only one background thread executes the submitted task (executors. newsinglethreadpool ()).


  2. Added the interface # executeonexecutor ()

    This interface allows developers to provide custom thread pools to run and schedule threads. If you want all tasks to run concurrently, create an unlimited thread pool (executors. newcachedthreadpool () and provide it to asynctask. In this way, the asynctask instance has its own thread pool and does not need to use the default asynctask.

  3. Two predefined thread pools are added.Serial_executorAndThread_pool_executor

    ActuallyThread_pool_executorIt is not newly added. It was previously available, but previously (Android 2.3) It was private to asynctask and was not made public.Thread_pool_executorIt is a thread pool with a corepoolsize of 5. That is to say, there are only five threads running at the same time, and more than five threads will have to wait. Therefore, if you use executeonexecutor (asynctask.Thread_pool_executorThe effect of route is the same as that of asynctask.exe cute () of Route 2.31.


    WhileSerial_executorIs added to ensure the task execution sequence, that is, it can ensure that the submitted tasks are indeed executed in a sequential order. Its internal queue is used to save the submitted tasks and ensure that only one task is currently running. This ensures that the tasks are executed in full order. The default execute () this is used, that is, executeonexecutor (asynctask.Serial_executor) Is the same as execute.

 

Solution to the preceding problem

After learning about asynctask, we can see the cause of the previous problem: because it is a 4.0 platform, all asynctask will not run in a separate thread, but will be executed by serial_executor in sequence. Because asynctask may be used in other places in the application, the asynctask to obtain the picture on the network may be executed only after all other tasks are completed, rather than immediately after Executor () is called.

The solution is actually very simple, either directly using thread or creating a separate thread pool (executors. newcachedthreadpool ()). Or the simplest solution is to use executeonexecutor (asynctask. thread_pool_executor). In this way, you do not have to wait until the previous execution is completed.

Precautions for using asynctask

In the previous article, we suggested using asynctask instead of thread, but asynctask seems to have its limitations. This requires you to select an appropriate tool based on your needs,No silver bullet.The following are some suggestions:

  • Improve your design,Less asynchronous Processing

    The thread overhead is very large, while asynchronous processing is also prone to errors, difficult to debug, difficult to maintain, so to improve your design, use Asynchronous as little as possible. For general database queries, a small number of I/O operations do not need to start threads.

  • With the main threadInteractionUse asynctask; otherwise, Use thread

    Asynctask is designed to meet the special needs of Android: Non-main threads cannot operate (UI) components. Therefore, asynctask extends the thread's ability to interact with the main thread. If your application does not interact with the main thread, you can simply use the thread.

  • When a large number of threads are required to execute tasksCreate Thread Pool

    The thread overhead is very large, especially when creating a new thread. Otherwise, you do not have to design tools such as the thread pool. When a large number of threads are required to execute tasks, you must create a thread pool, whether using asynctask or thread, because the number of internal thread pools of asynctask is limited and may not meet the requirements; to use thread, we need to manage the thread pool to avoid creating a large number of threads on the virtual machine. For example, if you want to download images in batches from the network, and you do not want to download images one by one or five, create a thread pool with corepoolsize of 10 or 20, 10 or 20 such downloads each time meet the speed, and do not consume useless performance overhead to create unlimited threads.

  • For Asynchronous tasks that want to start execution immediately, either use thread directly or create a thread pool separately for asynctask

    The default asynctask does not necessarily execute your task immediately unless you provide it with a separate thread pool. If you do not interact with the main thread, you can directly create a thread. Although the thread creation overhead is large, it is no problem if it is not a batch operation.

  • Android development is not as simple as you think. You need to spend more time on code and testing to ensure that the program is of high quality.

Attached resources:

Use the custom executor with corepoolsize of 7 (executors. newfixedthreadpool (7 )):


Use the unlimited' Executor (executors. newcachedthreadpool ()):

Attachment code: asynctest.zip

Related Article

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.