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>

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

相关文章
|
2月前
|
SQL 人工智能 Dart
Android Studio的插件生态非常丰富
Android Studio的插件生态非常丰富
114 1
|
2月前
|
Ubuntu Linux Android开发
Android Studio支持多种操作系统
Android Studio支持多种操作系统
104 1
|
2月前
|
前端开发 数据处理 Android开发
Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍
本文深入探讨了Flutter前端开发中的调试技巧与工具使用方法,涵盖调试的重要性、基本技巧如打印日志与断点调试、常用调试工具如Android Studio/VS Code调试器和Flutter Inspector的介绍,以及具体操作步骤、常见问题解决、高级调试技巧、团队协作中的调试应用和未来发展趋势,旨在帮助开发者提高调试效率,提升应用质量。
63 8
|
2月前
|
Linux Android开发 iOS开发
深入探索Android与iOS的多任务处理机制
在移动操作系统领域,Android和iOS各有千秋,尤其在多任务处理上展现出不同的设计理念和技术实现。本文将深入剖析两大平台在后台管理、资源分配及用户体验方面的策略差异,揭示它们如何平衡性能与电池寿命,为用户带来流畅而高效的操作体验。通过对比分析,我们不仅能够更好地理解各自系统的工作机制,还能为开发者优化应用提供参考。
|
2月前
|
数据可视化 开发工具 Android开发
Android Studio
Android Studio
152 1
|
2月前
|
算法 Linux 调度
深入探索安卓系统的多任务处理机制
【10月更文挑战第21天】 本文旨在为读者提供一个关于Android系统多任务处理机制的全面解析。我们将从Android操作系统的核心架构出发,探讨其如何管理多个应用程序的同时运行,包括进程调度、内存管理和电量优化等方面。通过深入分析,本文揭示了Android在处理多任务时所面临的挑战以及它如何通过创新的解决方案来提高用户体验和设备性能。
69 1
|
2月前
|
JSON JavaScript 前端开发
harmony-chatroom 自研纯血鸿蒙OS Next 5.0聊天APP实战案例
HarmonyOS-Chat是一个基于纯血鸿蒙OS Next5.0 API12实战开发的聊天应用程序。这个项目使用了ArkUI和ArkTS技术栈,实现了类似微信的消息UI布局、输入框光标处插入文字、emoji表情图片/GIF动图、图片预览、红包、语音/位置UI、长按语音面板等功能。
175 2
|
8月前
|
XML Java Android开发
Android实现自定义进度条(源码+解析)
Android实现自定义进度条(源码+解析)
139 1
|
8月前
|
XML API Android开发
Android 自定义View 之 圆环进度条
Android 自定义View 之 圆环进度条
132 0
|
8月前
|
XML API Android开发
Android 自定义View 之 饼状进度条
Android 自定义View 之 饼状进度条