update time:2019-2-21 author:要你命三千又三千 type:学习笔记
概念的简介
AsyncTask 是一个轻量级的异步任务类,是由谷歌提供的使用简单。
异步:异步对应于同步任务
同步任务是单线程的,顺序执行的任务,而异步对应于多线程的任务执行方式。(通俗理解同步任务就是顺序执行的任务,而异步任务就是在多个线程中执行的任务,异步任务之间一般需要通信)
因为Android程序刚启动时,会同时启动一个对应的主线程(Main Thread),这个主线程主要负责处理 与UI相关的事件!有时我们也把他称作UI线程!而在Android App时我们必须遵守这个单线程模型的规则: Android UI操作并不是线程安全的并且这些操作都需要在UI线程中执行! 假如我们在非UI线程中,比如在主线程中new Thread()另外开辟一个线程,然后直接在里面修改UI控件的值; 此时会抛出下述异常:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views 。 另外,还有一点,如果我们把耗时的操作都放在UI线程中的话,如果UI线程超过5s没有响应用于请求,那么 这个时候会引发ANR(Application Not Responding)异常,就是应用无响应~ 最后还有一点就是:Android 4.0后禁止在UI线程中执行网络操作~不然会报: android.os.NetworkOnMainThreadException
以上的种种原因都说明了Android引入异步任务的意义,当然实现异步也不可以不用到我们本节讲解 的AsyncTask,我们可以自己开辟一个线程,完成相关操作后,通过下述两种方法进行UI更新:
- 前面我们学的Handler,我们在Handler里写好UI更新,然后sendMessage()等的方法通知UI 更新,Handler写在主线程和子线程中是有区别的
- 利用Activity.runOnUiThread(Runnable)把更新ui的代码创建在Runnable中,更新UI时,把Runnable 对象传进来即可
实现简单的AsyncTask的实现
- 创建 AsyncTask 子类 & 根据需求实现核心方法
- 创建 AsyncTask子类的实例对象(即 任务实例)
- 手动调用execute()从而执行异步线程任务
AsyncTask的三个泛型参数说明(三个参数可以是任何类型)
class BitmapWorkTask extends AsyncTask<Integer,Integer,Bitmap>{…}
- 第一个参数:传入doInBackground()方法的参数类型 对应的execute()传入的参数
- 第二个参数:传入onProgressUpdate()方法的参数类型
- 第三个参数:传入onPostExecute()方法的参数类型,也doInBackground()方法返回的类型
@Override
protected Bitmap doInBackground(Integer... integers) {
data = integers[0];
return decodeSampleBitmapFromResources(getResources(),data,100,100);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if (weakReference != null && bitmap != null) {
final ImageView imageView = (ImageView) weakReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
使用实例:
<?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"
android:gravity="center"
>
<Button
android:layout_centerInParent="true"
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点我加载"/>
<TextView
android:id="@+id/text"
android:layout_below="@+id/button"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="还没开始加载!" />
<ProgressBar
android:layout_below="@+id/text"
android:id="@+id/progress_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:progress="0"
android:max="100"
style="?android:attr/progressBarStyleHorizontal"/>
<Button
android:layout_below="@+id/progress_bar"
android:layout_centerInParent="true"
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="cancel"/>
</RelativeLayout>
public class MainActivity extends AppCompatActivity {
MyTask mTask;
Button button,cancel; // 加载、取消按钮
TextView text; // 更新的UI组件
ProgressBar progressBar; // 进度条
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
cancel = findViewById(R.id.cancel);
text = findViewById(R.id.text);
progressBar = findViewById(R.id.progress_bar);
mTask = new MyTask();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTask.execute();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTask.cancel(true);
}
});
}
private class MyTask extends AsyncTask<String, Integer, String> {
// 方法1:onPreExecute()
// 作用:执行线程任务前的操作
@Override
protected void onPreExecute() {
text.setText("加载中");
// 执行前显示提示
}
// 方法2:doInBackground()
// 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
// 此处通过计算从而模拟“加载进度”的情况
//在子线程中运行
@Override
protected String doInBackground(String... params) {
try {
int count = 0;
int length = 1;
while (count<99) {
count += length;
// 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
publishProgress(count); //此方法自动调用onProgressUpdate()来执行
// 模拟耗时任务
Thread.sleep(50);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
// 方法3:onProgressUpdate()
// 作用:在主线程显示线程任务执行的进度
@Override
protected void onProgressUpdate(Integer... progresses) {
progressBar.setProgress(progresses[0]);
text.setText("loading..." + progresses[0] + "%");
}
// 方法4:onPostExecute()
// 作用:接收线程任务执行结果、将执行结果显示到UI组件
@Override
protected void onPostExecute(String result) {
// 执行完毕后,则更新UI
text.setText("加载完毕");
}
// 方法5:onCancelled()
// 作用:将异步任务设置为:取消状态
//当调用cancel()系统会调用onCancelled()方法。
@Override
protected void onCancelled() {
text.setText("已取消");
progressBar.setProgress(0);
}
}
}