运行有问题或需要源码请点赞关注收藏后评论区留言~~~
一、异步任务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>
创作不易 觉得有帮助请点赞关注收藏~~~