Android Studio App开发中异步任务AsynTask与异步服务IntentService的讲解与实战(实现四大名著的加载进度条 附源码)

简介: Android Studio App开发中异步任务AsynTask与异步服务IntentService的讲解与实战(实现四大名著的加载进度条 附源码)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~

一、异步任务AsyncTask

Thread+Handler方式虽然能够实现线程间通信,但是代码编写非常麻烦,并且难以维护,为了解决这个问题,Android提供了AsyncTask这个轻量级的异步任务工具,其内部已经封装好了Thread+Handler的通信机制。它是一个模板类,从他派生而来的任务类需要指定模板的参数类型

1:params 创建任务时的输入参数

2:Progress 执行任务时的处理进度

3:Result 完成任务时的结果参数

开发者自定义的任务类需要实现以下方法

1:onPreExecute 准备执行任务时触发

2:doInBackground 在后台执行的业务处理

3:onProgressUpdate  通常在处理过程中刷新进度条

4:onPostExecute  任务执行完毕时触发 显示处理结果

5:onCancelled 任务取消的回调操作

下面举个例子,电子书来自网络,要等它加载完毕后用户才能浏览电子书内容,于是编写电子书的异步加载任务,在界面上动态显示当前的加载进度,全部完成后再提示用户已经加载完毕。

代码如下

Java类

package com.example.chapter11;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.chapter11.task.BookLoadTask;
import com.example.chapter11.task.BookLoadTask.OnProgressListener;
@SuppressLint(value={"SetTextI18n","DefaultLocale"})
public class AsyncTaskActivity extends AppCompatActivity implements OnProgressListener {
    private TextView tv_async;
    private ProgressBar pb_async; // 声明一个进度条对象
    private ProgressDialog dialog; // 声明一个进度对话框对象
    public int mShowStyle; // 显示风格
    public int BAR_HORIZONTAL = 1; // 水平条
    public int DIALOG_CIRCLE = 2; // 圆圈对话框
    public int DIALOG_HORIZONTAL = 3; // 水平对话框
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);
        tv_async = findViewById(R.id.tv_async);
        // 从布局文件中获取名叫pb_async的进度条
        pb_async = findViewById(R.id.pb_async);
        initBookSpinner(); // 初始化书籍选择下拉框
    }
    // 初始化书籍选择下拉框
    private void initBookSpinner() {
        ArrayAdapter<String> styleAdapter = new ArrayAdapter<String>(this,
                R.layout.item_select, bookArray);
        Spinner sp_style = findViewById(R.id.sp_style);
        sp_style.setPrompt("请选择要加载的小说");
        sp_style.setAdapter(styleAdapter);
        sp_style.setOnItemSelectedListener(new StyleSelectedListener());
        sp_style.setSelection(0);
    }
    private String[] bookArray = {"三国演义", "西游记", "红楼梦"};
    private int[] styleArray = {BAR_HORIZONTAL, DIALOG_CIRCLE, DIALOG_HORIZONTAL};
    class StyleSelectedListener implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
            startTask(styleArray[arg2], bookArray[arg2]); // 启动书籍加载线程
        }
        public void onNothingSelected(AdapterView<?> arg0) {}
    }
    // 启动书籍加载线程
    private void startTask(int style, String book) {
        mShowStyle = style;
        BookLoadTask task = new BookLoadTask(book); // 创建一个书籍加载线程
        task.setOnProgressListener(this); // 设置书籍加载监听器
        task.execute(book); // 把书籍加载线程加入到处理列表
    }
    // 关闭对话框
    private void closeDialog() {
        if (dialog != null && dialog.isShowing()) { // 对话框仍在显示
            dialog.dismiss(); // 关闭对话框
        }
    }
    // 在线程处理结束时触发
    public void onFinish(String book) {
        String desc = String.format("您要阅读的《%s》已经加载完毕", book);
        tv_async.setText(desc);
        closeDialog(); // 关闭对话框
    }
    // 在线程处理取消时触发
    public void onCancel(String result) {}
    // 在线程处理过程中更新进度时触发
    public void onUpdate(String book, int progress) {
        String desc = String.format("%s当前加载进度为%d%%", book, progress);
        tv_async.setText(desc); // 设置加载进度的文本内容
        if (mShowStyle == BAR_HORIZONTAL) { // 水平条
            pb_async.setProgress(progress); // 设置水平进度条的当前进度
        } else if (mShowStyle == DIALOG_HORIZONTAL) { // 水平对话框
            dialog.setProgress(progress); // 设置水平进度对话框的当前进度
        }
    }
    // 在线程处理开始时触发
    public void onBegin(String book) {
        tv_async.setText(book + "开始加载");
        if (dialog == null || !dialog.isShowing()) {  // 进度框未弹出
            if (mShowStyle == DIALOG_CIRCLE) { // 圆圈对话框
                // 弹出带有提示文字的圆圈进度对话框
                dialog = ProgressDialog.show(this, "稍等", book + "页面加载中……");
            } else if (mShowStyle == DIALOG_HORIZONTAL) { // 水平对话框
                dialog = new ProgressDialog(this); // 创建一个进度对话框
                dialog.setTitle("稍等"); // 设置进度对话框的标题文本
                dialog.setMessage(book + "页面加载中……"); // 设置进度对话框的内容文本
                dialog.setIcon(R.drawable.ic_search); // 设置进度对话框的图标
                dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); // 设置进度样式
                dialog.show(); // 显示进度对话框
            }
        }
    }
}

任务类

package com.example.chapter11.task;
import android.os.AsyncTask;
// 模拟异步处理的线程
public class BookLoadTask extends AsyncTask<String, Integer, String> {
    private String mBook; // 书籍名称
    public BookLoadTask(String title) {
        super();
        mBook = title;
    }
    // 线程正在后台处理
    protected String doInBackground(String... params) {
        int ratio = 0; // 下载比例
        for (; ratio <= 100; ratio += 5) {
            try {
                Thread.sleep(200); // 睡眠200毫秒模拟网络文件下载耗时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            publishProgress(ratio); // 通报处理进展。调用该方法会触发onProgressUpdate方法
        }
        return params[0]; // 返回参数是书籍的名称
    }
    // 准备启动线程
    protected void onPreExecute() {
        mListener.onBegin(mBook); // 触发监听器的开始事件
    }
    // 线程在通报处理进展
    protected void onProgressUpdate(Integer... values) {
        mListener.onUpdate(mBook, values[0]); // 触发监听器的进度更新事件
    }
    // 线程已经完成处理
    protected void onPostExecute(String result) {
        mListener.onFinish(result); // 触发监听器的结束事件
    }
    // 线程已经取消
    protected void onCancelled(String result) {
        mListener.onCancel(result); // 触发监听器的取消事件
    }
    private OnProgressListener mListener; // 声明一个进度更新的监听器对象
    // 设置进度更新的监听器
    public void setOnProgressListener(OnProgressListener listener) {
        mListener = listener;
    }
    // 定义一个进度更新的监听器接口
    public interface OnProgressListener {
        void onBegin(String book); // 在线程处理开始时触发
        void onUpdate(String book, int progress); // 在线程处理过程中更新进度时触发
        void onFinish(String book); // 在线程处理结束时触发
        void onCancel(String book); // 在线程处理取消时触发
    }
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp" >
        <TextView
            android:id="@+id/tv_style"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:gravity="center"
            android:text="请选择要加载的小说 "
            android:textColor="@color/black"
            android:textSize="17sp" />
        <Spinner
            android:id="@+id/sp_style"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_toRightOf="@+id/tv_style"
            android:gravity="left|center"
            android:spinnerMode="dialog" />
    </RelativeLayout>
    <ProgressBar
        android:id="@+id/pb_async"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="30dp" />
    <TextView
        android:id="@+id/tv_async"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这里查看加载进度"
        android:textColor="@color/black"
        android:textSize="17sp" />
</LinearLayout>

二、异步服务IntentService

服务虽然在后台运行,但它跟活动一样都在主线程中,如果后台运行的服务堵塞,用户界面就会卡着不动,俗称死机,因此我们可以使用Android封装好的异步服务IntentService有以下两个好处

1:免去复杂的消息通信流程

2:处理完成后无须手工停止服务,开发者可集中经理编写业务逻辑

开发者在定义异步服务时要注意以下四点

1:增加一个构造方法 并分配内部线程的唯一名称

2:onStartCommand方法要调用父类

3:耗时处理的业务代码要写在onHandlerIntent方法中

4:异步服务只能通过普通方式启停 不能通过绑定方式启停

效果如下 异步服务不影响主界面的操作

代码如下

Java类

package com.example.chapter11;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.chapter11.service.AsyncService;
import com.example.chapter11.util.DateUtil;
@SuppressLint("SetTextI18n")
public class IntentServiceActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView tv_intent;
    private Handler mHandler = new Handler(); // 声明一个处理器对象
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_intent_service);
        tv_intent = findViewById(R.id.tv_intent);
        findViewById(R.id.btn_intent).setOnClickListener(this);
        mHandler.postDelayed(mService, 100); // 延迟100毫秒后启动异步任务
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_intent) {
            tv_intent.setText(DateUtil.getNowTime() + " 您轻轻点了一下下(异步服务正在运行,不影响您在界面操作)");
        }
    }
    private Runnable mService = new Runnable() {
        @Override
        public void run() {
            // 构建通往异步服务的意图
            Intent intent = new Intent(IntentServiceActivity.this, AsyncService.class);
            startService(intent); // 启动意图设定的异步服务
        }
    };
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <Button
        android:id="@+id/btn_intent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="5dp"
        android:text="点我看看有没有反应"
        android:textColor="@color/black"
        android:textSize="17sp" />
    <TextView
        android:id="@+id/tv_intent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="5dp"
        android:text="这里查看点击结果"
        android:textColor="@color/black"
        android:textSize="17sp" />
</LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

相关文章
|
1月前
|
Java 数据库 Android开发
Android异步之旅:探索AsyncTask
Android异步之旅:探索AsyncTask
23 0
|
6天前
|
测试技术 Android开发
Android App获取不到pkgInfo信息问题原因
Android App获取不到pkgInfo信息问题原因
14 0
|
18天前
|
监控 数据可视化 安全
智慧工地SaaS可视化平台源码,PC端+APP端,支持二开,项目使用,微服务+Java++vue+mysql
环境实时数据、动态监测报警,实时监控施工环境状态,有针对性地预防施工过程中的环境污染问题,打造文明生态施工,创造绿色的生态环境。
14 0
智慧工地SaaS可视化平台源码,PC端+APP端,支持二开,项目使用,微服务+Java++vue+mysql
游戏直播APP平台开发多少钱成本:定制与成品源码差距这么大
开发一款游戏直播APP平台所需的费用是多少?对于计划投身这一领域的投资者来说,首要关心的问题之一就是。本文将探讨两种主要的开发模式——定制开发与成品源码二次开发的成本差异及其优劣势。
|
1月前
|
传感器 人工智能 数据可视化
Java智慧工地监管一体化云平台APP源码 SaaS模式
高支模监测:高支模立杆及倾斜角度,高支模立杆的荷载,架体的水平位移以及模板沉降情况,当检测数据超过预警值时,实时报警。
32 2
|
1月前
|
人工智能 监控 前端开发
Java智慧城管系统源码 数字城管APP系统源码 城市管理综合执法监督系统源码
Java编写的智慧城管系统源码,包含数字城管APP和综合执法监督系统,运用物联网、云计算等技术实现城市全面智慧管理。系统采用微服务架构,Java开发,结合vue前端框架和SpringBoot后端框架,支持MySQL数据库和uniapp移动端。功能模块包括执法办案、视频分析、统计分析等,提升案件办理和监管效能,促进行政执法创新,实现电子送达和非接触执法。
20 1
|
1月前
|
开发框架 移动开发 JavaScript
SpringCloud微服务实战——搭建企业级开发框架(四十六):【移动开发】整合uni-app搭建移动端快速开发框架-环境搭建
正如优秀的软件设计一样,uni-app把一些移动端常用的功能做成了独立的服务或者插件,我们在使用的时候只需要选择使用即可。但是在使用这些服务或者插件时一定要区分其提供的各种服务和插件的使用场景,例如其提供的【uni-starter快速开发项目模版】几乎集成了移动端所需的所有基础功能,使用非常方便,但是其许可协议只允许对接其uniCloud的JS开发服务端,不允许对接自己的php、java等其他后台系统。
146 2
|
1月前
|
编解码 小程序 算法
短剧系统开发(网页版/APP/小程序)丨短剧系统开发运营版及源码出售
短剧系统开发功能旨在为用户提供观看、分享和交流短剧作品的平台,涉及多种功能和特性,
|
1月前
|
移动开发 负载均衡 小程序
代驾app开发丨代驾系统开发玩法详情丨代驾系统开发网页版/H5/小程序及源码部署
**司机/代驾员端**:司机可以通过APP接收订单,查看订单详情、路线和导航,提供现场服务并进行确认。
|
1月前
|
Android开发 开发者
Android异步之旅:探索IntentService
Android异步之旅:探索IntentService
20 0