40. 【Android教程】AsyncTask:异步任务

在前面的章节有提到过,Android 系统默认会在主线程(UI 线程)执行任务,但是如果有耗时程序就会阻塞 UI 线程,导致页面卡顿。这时候我们通常会将耗时任务放在独立的线程,然后通过 Handler 等线程间通信机制完成 UI 的刷新。很多时候我们也许只是想执行一个简单的任务,为此写一套 Handler 线程通信就会显得比较复杂,不用担心,Android 系统为我们提供了一个专门用于执行异步任务的工具——Async Task,它可以让我们执行后台任务并轻松的与 UI 线程进行状态同步,今天就一起来学习一下 AyncTask 的用法。

1. AsyncTask 简介

AsyncTask 类通常用来在执行后台任务的同时刷新 UI,通过调用execute()方法触发后台任务的执行,首先会回调 AsyncTask 的onPreExecute(),接着回调doInBackground()来执行自定义的后台任务,最后回调onPostExecute()方法用来刷新 UI,整体流程示意图如下:

2. AsyncTask 的基本用法

2.1 声明 AsyncTask

我们不能直接创建 AsyncTask,正确的方法是继承自 AsyncTask 实现一个它的子类,如下:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
        protected Long doInBackground(URL... urls) {
             // 执行后台耗时任务
            return;
        }

        protected void onProgressUpdate(Integer... progress) {
            // 任务执行进度更新
        }

        protected void onPostExecute(Long result) {
            // 执行完毕,更新UI
        }
    }

以上是 AsyncTask 的核心回调方法,每个方法的含义会在后面具体讲到。

2.2 指定参数

AsyncTask 可以帮助你在子线程和主线程之间同步参数,根据不同的业务场景,参数类型和个数也会不一样。刚刚在 2.1 小节声明 AyncTask 子类的时候,需要传入 3 个泛型参数:

  • TypeOfVarArgParams:
    在任务启动之后,传入给后台任务的参数类型

  • ProgressValue:
    启动之后到任务结束之间,系统会不断回调此方法,用来更新任务的进度

  • ** ResultValue:**
    后台任务的执行结果

2.3 启动后台任务

在声明完后台任务之后,就可以直接启动了。启动方式比较简单,直接通过调用execute()方法启动后台任务:

new DownloadFilesTask().execute(url1, url2, url3);

3 AsyncTask 关键回调方法

AsyncTask 是由 4 个回调方法配合组成,这 4 个回调方法按照一定的顺序依次被调用,所以我们需要 focus 的是在正确的回调方法中实现我们想要的逻辑,下面详细看看如何使用。

  • onPreExecute():
    在执行execute()方法之后该方法立即被调用,标志着 AyncTask 正式开启。通常用来做一些需要在后台任务开启之前完成的初始化工作,比如展示一个进度条、或者弹出一个对话框等等。该方法在 UI 线程执行。
  • doInBackground(Params):
    在执行完onPreExecute()方法之后立即被调用,用来执行需要放在后台执行的耗时任务。在创建 AsyncTask 的时候传入的参数就是提供给doInBackground使用的。在后台任务执行完毕后,还需要将执行结果返回到onPostExecutes ()中,同时我们也可以通过publishProgress(Progress…)方法来手动发布任务进度,进度将从子线程发送到 UI 线程。毋庸置疑,该方法在子线程中执行。
  • onProgressUpdate(Progress…):
    当我们通过publishProgress(Params)发布进度之后,系统会回调该方法,用来获取任务执行进度并更新 UI。这一步就完成了子线程到主线程的通信,该方法在 UI 线程执行
  • onPostExecute(Result):
    当后台任务执行完毕,该方法被回调,同时标志着整个 AyncTask 结束。与onPreExecute相反,通常会在onPostExecute中做一些回收工作,比如提示“下载完成”、“加载失败”、隐藏进度条等等。

4 AsyncTask 示例

本节的功能和第 38 节 Handler 的功能类似,我们还是完成一个后台执行耗时任务,并同步更新进度条的功能,可以直接在 Handler 的例子上修改。

4.1 布局文件

布局文件基本一样,只是默认将进度条和进度显示隐藏起来,等到onPreExecute()方法的时候在做初始化展示,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ProgressBar
        android:visibility="gone"
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true" />

    <Button
        android:id="@+id/start_progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/progressBar"
        android:layout_alignParentStart="true"
        android:layout_marginStart="24dp"
        android:layout_marginTop="62dp"
        android:text="开始任务" />

    <TextView
        android:visibility="gone"
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/start_progress"
        android:layout_alignBottom="@+id/start_progress"
        android:layout_alignParentEnd="true"
        android:layout_marginEnd="85dp"
        android:gravity="center"
        android:text="当前进度:0%"
        android:textSize="16sp" />

</RelativeLayout>

4.2 异步任务控制

异步任务的代码基本上和 Handler 一致,我们通过Thread.sleep(1000)来模拟一秒钟的耗时操作,然后在onPreExecute()中展示进度条,在后台任务执行完后通过publishProgress(int)来将任务进度发送到主线程,由onProgressUpdate(int)方法在 UI 线程接收进度,并更新进度条。最后在结束的时候返回“已完成”提示,在onPostExecute(String)方法中进行收尾工作,隐藏进度条并展示“已完成”。代码如下:

package com.emercy.myapplication;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends Activity {

    private static final int MAX = 100;

    private ProgressBar progressBar;
    private Button startProgress;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        progressBar = findViewById(R.id.progressBar);
        startProgress = findViewById(R.id.start_progress);
        textView = findViewById(R.id.textView);
        progressBar.setMax(MAX);

        startProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new DownloadTask().execute();
            }
        });
    }

    // 1、创建Async Task子类
    private class DownloadTask extends AsyncTask<Integer, Integer, String> {

        // 2、初始化阶段,展示进度条
        @Override
        protected void onPreExecute() {
            progressBar.setVisibility(View.VISIBLE);
            textView.setVisibility(View.VISIBLE);
        }

        // 3、执行后台任务
        @Override
        protected String doInBackground(Integer... integers) {
            int i;
            for (i = 0; i < 100; i++) {
                try {
                    // 一秒钟的耗时操作
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 4、发布进度
                publishProgress(i);
            }
            return "异步任务已完成";
        }

        // 5、接收后台任务数据并更新进度条
        @Override
        protected void onProgressUpdate(Integer... values) {
            textView.setText("当前进度:" + values[0] + "%");
            progressBar.setProgress(values[0]);
        }

        // 6、任务结束
        @Override
        protected void onPostExecute(String s) {
            progressBar.setVisibility(View.GONE);
            textView.setText(s);
        }
    }
}

编译之后,效果如下:

可以看到大体的效果和 Handler 是一样的,但是整个异步任务的处理流程更加清晰了,而且可以很方便的做任务前的初始化任务后的回收工作,整个线程的切换也不再需要我们去控制,全部交给 AsyncTask 操作就行,一切就是这么简单!

5 小结

本节介绍了一个专门用于执行异步任务的工具类,首先需要创建一个子类继承自 AsyncTask,然后确定好需要传入和返回的参数类型,接着覆写 4 个关键的方法,剩下的线程切换及数据传输就交给系统完成了。
相比 Handler,AsyncTask使用更简单,我们只需要关注我们的后台逻辑,而 Handler 需要我们自行管理的东西比较多。所以在执行后台任务刷新 UI 的场景,强烈推荐使用 AsyncTask,可以让我们的开发更加顺畅。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/569977.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

扁平与圆形Cat6网线:区别与选择指南

&#x1f335;在构建家庭或办公室网络时&#xff0c;选择合适的网线类型至关重要。Cat6网线因其高速传输性能而广受欢迎&#xff0c;但在购买时&#xff0c;您可能会发现市场上有两种不同形状的Cat6网线&#xff1a;扁平和圆形。本文将探讨这两种网线的区别&#xff0c;并提供选…

用html写一个旋转菜单

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>旋转菜单</title><link relstylesheet href"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"&…

百兆集成网络链接器911105A

百兆集成网络链接器&#xff08;有时也称为百兆网卡&#xff09;是一种硬件设备&#xff0c;主要用于计算机与计算机网络之间的高速数据传输。它的主要功能包括&#xff1a; 1. 高速数据传输&#xff1a;百兆集成网络链接器支持100Mbps的数据传输速率&#xff0c;比之前的以太…

河道采砂执法监管信息化平台:科技赋能,智慧监管

随着信息技术的飞速发展&#xff0c;信息化平台已经成为提升行业监管效率和水平的重要工具。河道采砂作为水利资源管理的重要环节&#xff0c;其执法监管同样需要与时俱进&#xff0c;利用先进技术手段提升监管效能。河道采砂执法监管信息化平台便是这一背景下的产物&#xff0…

某酒业集团数字化转型规划(169页附下载)

某酒业集团数字化转型项目实施方案建议书(P169).rar是一个极具参考价值的资料&#xff0c;它详细地阐述了如何利用数字化技术来推动企业转型。这份建议书以IBM的先进技术和某酒业集团的实际应用需求为基础&#xff0c;提出了一套全面、系统的数字化转型解决方案。该方案首先对某…

在linux系统打开pycharm,为pycharm在桌面设置图标

1.打开终端输入&#xff1a;gedit /usr/share/applications/Pycharm.desktop 然后会弹出一个文件 2.在文件中写入&#xff1a; [Desktop Entry] TypeApplication NamePycharm GenericNamePycharm3 CommentPycharm3:The Python IDE Execsh /home/.../pycharm.sh #自己pych…

【kettle002】kettle访问人大金仓KingbaseES数据库并处理数据至execl文件

一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 熟悉、梳理、总结下人大金仓KingbaseES数据库相关知识体系 kettle访问人大金仓KingbaseES数据库…

Centos之yum安装好玩的命令

1.会动的小火车 我在root下使用的 yum install sl.x86_64sl2.figlet yum install figlet.x86_64figlet 55553.cowsay会说话 yum install cowsay

javaScript基础3

javaScript 一.对象1.概念2.创建对象的三种方法(1).字面量创建&#xff08;利用{}&#xff09;(2)变量、属性、函数、方法的区别(3).new Object创建(4).构造函数 3.new关键字的执行过程4.遍历对象&#xff08;for..in) 二.内置对象1.了解2.math对象3.日期对象&#xff08;构造函…

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡

【声呐仿真】学习记录0.5-配置ssh远程连接docker、在docker中使用nvidia显卡 配置ssh远程连接docker1.端口映射2.配置ssh 在docker中使用nvidia显卡配置CUDA 注意&#xff1a;之前已经创建过容器的&#xff0c;需要打包成镜像&#xff0c;重新创建容器&#xff0c;因为要在创建…

伐木机不要石头!!!

伐木机不要石头&#xff01;&#xff01;&#xff01;(easy version) 本题有对应的hard version&#xff0c;区别仅在多次询问中。保证easy version的测试用例集是hard version的真子集&#xff0c;通过困难版本的代码经过简单修改可直接通过简单版 看着家里贫瘠的资源&#x…

【Python学习】面向对象

面向对象 1.初识对象1.1 生活中数据的组织1. 2 程序中数据的组织1.3 使用对象组织数据1.4进行对比 2. 成员方法2.1 类的定义和使用2.2 成员变量和成员方法2.2.1 成员变量2.2.2 成员方法的定义语法2.2.3 self 的作用 3. 类和对象3.1 面向过程3.2 面向对象 4.构造方法4.1 属性成员…

用Vue做一个待办事项

这个待办事项有以下功能&#xff1a;增删查&#xff0c;既新增待办事项&#xff0c;删除待办事项&#xff0c;查看全部&#xff0c;未完成&#xff0c;完成待办事项&#xff0c;当鼠标移动到待办事项上时会显示删除按钮 分为四个部分来实现&#xff1a;ToDoHeader.vue、ToDoMai…

XYCTF 部分wp及学习记录

1.ezmd5 根据题目提示 我们知道应该是要上传两张md5值相同的图片 根据原文链接&#xff1a;cryptanalysis - Are there two known strings which have the same MD5 hash value? - Cryptography Stack Exchange 把保存下来的图片上传一下 得到flag 2.ezhttp 根据原文链接&…

多臂老虎机介绍【Multi-armed Bandits】

强化学习笔记 主要基于b站西湖大学赵世钰老师的【强化学习的数学原理】课程&#xff0c;个人觉得赵老师的课件深入浅出&#xff0c;很适合入门. 第一章 强化学习基本概念 第二章 贝尔曼方程 第三章 贝尔曼最优方程 第四章 值迭代和策略迭代 第五章 强化学习实践—GridWorld 第…

Python基础05-数学运算与排列组合生成

在Python中进行数学运算和生成排列组合是数据科学、机器学习和日常编程中常见的任务。本文将介绍如何在Python中执行基本的数学运算、处理复数、使用数学函数、生成排列和组合、随机数生成、处理分数、统计函数以及处理无穷大和NaN值。 1. 基本算术运算 Python支持传统的四则…

26版SPSS操作教程(高级教程第十三章)

前言 #今日世界读书日&#xff0c;宝子你&#xff0c;读书了嘛~ #本期内容&#xff1a;主成分分析、因子分析、多维偏好分析 #由于导师最近布置了学习SPSS这款软件的任务&#xff0c;因此想来平台和大家一起交流下学习经验&#xff0c;这期推送内容接上一次高级教程第十二章…

【剪映专业版】05文字重叠

【剪映专业版】05文字重叠 1.在素材库中搜索纯黑背景&#xff0c;添加文本&#xff0c;设置合适的字体、字号等&#xff0c;导出备用。 2.返回窗口&#xff0c;设置字体颜色为纯黑&#xff0c;勾选描边设置描边为纯白&#xff0c;描边粗细值为8。导出备用。 3.将视频素材导入。…

SpringCloud系列(11)--将微服务注册进Eureka集群

前言&#xff1a;在上一章节中我们介绍并成功搭建了Eureka集群&#xff0c;本章节则介绍如何把微服务注册进Eureka集群&#xff0c;使服务达到高可用的目的 Eureka架构原理图 1、分别修改consumer-order80模块和provider-payment8001模块的application.yml文件&#xff0c;使这…

Win10 打开有些软件主界面会白屏不显示,其他软件都正常

环境&#xff1a; Win10专业版 英伟达4070 显卡 问题描述&#xff1a; Win10 打开有些软件主界面会白屏不显示,打开远程协助软件AIRMdesk,白色&#xff0c;其他软件都正常 解决方案&#xff1a; 网上说电脑没有接显示器独立显卡的关系导致 我是只有一台主机&#xff0c;没…