Android AsyncTasks并行执行

In this tutorial, we’ll be digging deep into AsyncTasks in android by discussing the different ways of executing it. We’ll see the different ways to handle configuration changes with Async Tasks too.
To know the basics of AsyncTasks, we recommend you to read this tutorial.

在本教程中,我们将通过讨论执行它的不同方法来深入研究android中的AsyncTasks。 我们还将看到使用异步任务处理配置更改的不同方法。
要了解AsyncTasks的基础知识,建议您阅读教程。

Android AsyncTasks (Android AsyncTasks)

AsyncTasks is a helper class that lets us run background tasks which can communicate back with the UI thread.

AsyncTasks是一个帮助程序类,它使我们可以运行可以与UI线程通讯回来的后台任务。

Following are the main methods provided by the AsyncTask class:

以下是AsyncTask类提供的主要方法:

  • onPreExecute

    onPreExecute
  • doInBackGround

    doInBackGround
  • onPostExecute

    onPostExecute
  • onProgressUpdate – In order to invoke this, call the publishProgress method from the doInBackground method.

    onProgressUpdate –为了调用此方法,请从doInBackground方法中调用publishProgress方法。

The syntax to declare an AsyncTask is:

声明AsyncTask的语法是:

private static class MyAsyncTask extends AsyncTask<A, B, C>

Three types of arguments are passed :

传递了三种类型的参数:

  • A – These are the type of params that can be passed in the execute() method. They are used in the doInBackground.

    答–这些是可以在execute()方法中传递的参数类型。 它们在doInBackground中使用。
  • B – This type is available in the onProgressUpdate

    B –此类型在onProgressUpdate可用
  • C – This is the type present in the onPostExecute method.

    C –这是onPostExecute方法中存在的类型。

execute method is invoked on the instance to start the AsyncTask typically.

通常在实例上调用execute方法以启动AsyncTask。

AsyncTasks should be declared static. Otherwise, leaks would occur since non-static classes contain direct references to the Activities which can prevent the Activity from getting garbage collected if its closed while the AsyncTask is still running.
AsyncTasks应该声明为静态。 否则,会发生泄漏,因为非静态类包含对Activity的直接引用,如果AsyncTask仍在运行时关闭了该Activity,则可以防止该Activity被垃圾回收。

AsyncTasks并行执行 (AsyncTasks Parellel Execution)

Till Android Donut, Parallel Execution was not possible when multiple AsyncTasks were executed simultaneously.

到Android Donut为止,当同时执行多个AsyncTask时,并行执行是不可能的。

From Android Donut multiple async tasks were executed in parallel until Android Honeycomb 3.0 arrived.

从Android Donut并行执行多个异步任务,直到Android Honeycomb 3.0到来。

In order to do parallel Execution since Android 3.0, we need to call the method, executeOnExecutor(java.util.concurrent.Executor, Object[]) on the AsyncTask.

为了从Android 3.0开始执行并行执行,我们需要在AsyncTask上调用方法executeOnExecutor(java.util.concurrent.Executor, Object[])

Here a THREAD_POOL_EXECUTOR is passed for the Executor.

在这里,为执行器传递了THREAD_POOL_EXECUTOR

Note: AsyncTask is built using Java’s Executor Service

注意:AsyncTask是使用Java的Executor服务构建的

How many AsyncTasks are executed in parallel? 并行执行多少个AsyncTask?

It depends on:
Core Pool Size (CORE_POOL_SIZE) (# of threads in the thread pool) = CPU Count + 1

这取决于:
核心池大小(CORE_POOL_SIZE)(线程池中的线程数)= CPU计数+ 1

Maximum Pool Size (MAXIMUM_POOL_SIZE) (max # of thread in the thread pool) = CPU Count * 2 +1

最大池大小(MAXIMUM_POOL_SIZE)(线程池中的最大线程数)= CPU计数* 2 +1

So for a smartphone with 4 core processor, 4*2 + 1 = 9 AsyncTasks can be run in parallel.

因此,对于具有4核心处理器的智能手机,可以并行运行4 * 2 + 1 = 9 AsyncTasks。

AsyncTasks内存泄漏和方向更改 (AsyncTasks Memory Leaks And Orientation Changes)

Whenever you define an AsyncTask in your code, the IDE does ask you to set the class as static inner class or memory leaks might occur. Why so?

每当您在代码中定义AsyncTask时,IDE都会要求您将类设置为静态内部类,否则可能会发生内存泄漏。 为什么这样?

Non-static inner classes hold a direct reference to the parent class. So if an AsyncTask lives longer than the Activity, it will prevent the Activity from getting garbage collected.

非静态内部类直接引用父类。 因此,如果AsyncTask的寿命长于Activity,则将阻止Activity收集垃圾。

Thus, we can define the AsyncTask as static or keep a WeakReference to the Activity in it.

因此,我们可以将AsyncTask定义为静态,或在其中保留对Activity的WeakReference。

A static object’s lifecycle is bound to the class it is contained in.
静态对象的生命周期绑定到其所包含的类。

An orientation change can cause IllegalStateException since the enclosed activities configuration changes while the AsyncTask is running in the background. This can lead to memory leaks.

方向更改可能会导致IllegalStateException,因为在AsyncTask在后台运行时,随附的活动配置会更改。 这可能导致内存泄漏。

So setting android:configChanges = “orientation” is one way to deal with AsyncTask and Screen rotation.
But this isn’t a good practice.

因此,设置android:configChanges =“ orientation”是处理AsyncTask和屏幕旋转的一种方法。
但这不是一个好习惯。

Another possible way is by locking the orientation to the current one in the onPreExecute and unlocking in the onPostExecute after the background work is over.

另一种可能的方法是,将方向锁定为onPreExecute中的当前方向,然后在后台工作结束后在onPostExecute中解锁。

The ideal way is to put an AsyncTask inside a Fragment and setRetainInstance(true).

理想的方法是将AsyncTask放入Fragment和setRetainInstance(true)

For the sake of simplicity and since we are focusing on Parallel Execution in this tutorial, we’ll set the configChanges in the AndroidManifest.xml file in our below project code.

为了简单起见,由于在本教程中我们将重点放在并行执行上,因此我们将在下面的项目代码中的AndroidManifest.xml文件中设置configChanges。

项目结构 (Project Structure)

(Code)

The code for the activity_main.xml layout is given below:

下面给出了activity_main.xml布局的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <ProgressBar
        android:id="@+id/progressBar1"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10" />


    <ProgressBar
        android:id="@+id/progressBar2"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10" />


    <Button
        android:id="@+id/btnSerialExecution"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SERIAL EXECUTION" />


    <ProgressBar
        android:id="@+id/progressBar3"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10" />


    <ProgressBar
        android:id="@+id/progressBar4"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10" />


    <Button
        android:id="@+id/btnParallelExecution"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="PARELLEL EXECUTION" />

</LinearLayout>

We’ve created 4 ProgressBar, 2 will be filled serially using AsyncTask progress updates and the remaining two would be executed parallelly. Let’s see the code for it.

我们已经创建了4个ProgressBar,其中2个将使用AsyncTask进度更新顺序填充,其余两个将并行执行。 让我们看看它的代码。

package com.journaldev.androidmultiasynctasks;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    Button btnParallelExecution, btnSerialExecution;
    ProgressBar progressBar1, progressBar2, progressBar3, progressBar4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initViews();
    }

    private void initViews() {
        btnSerialExecution = findViewById(R.id.btnSerialExecution);
        progressBar1 = findViewById(R.id.progressBar1);
        progressBar2 = findViewById(R.id.progressBar2);
        btnParallelExecution = findViewById(R.id.btnParallelExecution);
        progressBar3 = findViewById(R.id.progressBar3);
        progressBar4 = findViewById(R.id.progressBar4);

        btnSerialExecution.setOnClickListener(this);
        btnParallelExecution.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {

        switch (view.getId()) {
            case R.id.btnSerialExecution:

                MyObject myObject = new MyObject(progressBar1, 2);

                MyAsyncTask aTask1 = new MyAsyncTask();
                aTask1.execute(myObject);

                myObject = new MyObject(progressBar2, 3);

                MyAsyncTask aTask2 = new MyAsyncTask();
                aTask2.execute(myObject);
                break;

            case R.id.btnParallelExecution:

                myObject = new MyObject(progressBar3, 2);

                MyAsyncTask aTask3 = new MyAsyncTask();
                aTask3.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, myObject);

                myObject = new MyObject(progressBar4, 3);

                MyAsyncTask aTask4 = new MyAsyncTask();
                aTask4.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, myObject);
                break;
        }

    }

    private static class MyAsyncTask extends AsyncTask<MyObject, Integer, Void> {

        private WeakReference<MyObject> myObjectWeakReference;

        @Override
        protected Void doInBackground(MyObject... params) {
            this.myObjectWeakReference = new WeakReference<>(params[0]);
            for (int i = 0; i <= 10; i++) {
                publishProgress(i);

                try {
                    Thread.sleep(myObjectWeakReference.get().interval * 100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }


        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            myObjectWeakReference.get().progressBar.setProgress(values[0]);
        }
    }

    private class MyObject {
        private ProgressBar progressBar;
        private int interval;

        MyObject(ProgressBar progressBar, int interval) {
            this.progressBar = progressBar;
            this.interval = interval;
        }
    }
}

We’ve created a Model class which is passed in the AsyncTask param.
It contains the ProgressBar instance and the interval for which the Thread would sleep.

我们创建了一个Model类,该类在AsyncTask参数中传递。
它包含ProgressBar实例以及线程将Hibernate的时间间隔。

The output of the above application in action is given below:

上面应用程序的输出如下:

This brings an end to this tutorial. You can download the project from the link below:

本教程到此结束。 您可以从下面的链接下载项目:

翻译自: https://www.journaldev.com/23605/android-asynctasks-parallel-execution

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值