异步处理工具类:AsyncTask

前言

我们都知道在主线程子线程之间的通信主要依靠Handler完成,但子线程无法直接对主线程的组件进行更新,在android1.5后提供了一个android.os.AsyncTask(非同步任务)类,我们可以通过此类完成非阻塞的操作类。该类和Handler类似,可以在后台进行操作之后更新主线程的UI,但它的使用要比Handler容易许多。

正文

AsyncTask是异步任务,那么为什么要有异步任务?

我们首先就需要知道Android是单线程模型(关于何为单线程,请看这里),还有就是我们要知道Android要求耗时操作不可以在主线程中执行。由此我们必须想到相对应得解决办法。AsyncTask由此而生。

它可以在子线程中去更新我们的UI,封装、简化异步操作

android.os.AsyncTask类的继承结构如下:

java.lang.Object

  ===>android.os.AsyncTask<Params,Progress,Result>

AsyncTask<Params,Progress,Result>是一个抽象类,而抽象类需要被继承,继承AsyncTask需要指定如下三个泛型参数:

  • Params:启动时需要的参数类型,如每次操作的休眠时间为Integer。
  • Progress:后台执行任务的百分比,如进度条需要传递的是Integer。
  • Result:后台执行完毕之后返回的信息,如完成数据信息显示传递的是String。

android.os.AsyncTask类中定义的常用方法:

1.public final boolean cancel(boolean mayInterruptIfRunning)  普通类型   指定是否取消当前线程操作

2.public final AsyncTask<Params,Progress,Result> execute(Params...params)  普通类型  执行AsyncTask操作

3.public final boolean isCancelled()  普通类型  判断子线程是否被取消

4.public final void publishProgress(Progress...values)  普通  更新线程进度

5.protected abstract Result doInBackground(Params...params)  普通类型  在后台完成任务执行,可以调用publishProgress()方法更新线程进度

6.protected void onProgressUpdate(Progress...values)  普通类型  在主线程中执行,用于显示任务的进度

7.protected void onPreExecute()  普通类型  在主线程中执行,在doInBackground()之前执行

8.protected void onPostExecute(Result result)  普通类型  在主线程中执行,方法参数为任务执行结果

9.protected void onCancelled()  普通类型  在主线程中执行,在cancel()方法之后执行

上面介绍了我们的AsyncTask常用的方法,但在实际开发中,更多的是覆写如写几个方法:

  • doInBackground:必须重写,异步执行后台线程将要完成的任务
  • onPreExecute:执行后台耗时操作前被调用,通常用户完成一些初始化操作
  • onPostExecute:当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground方法返回的值传给该方法
  • onProgressUpdate:在doInBackground()方法中调用publishProgress()方法,更新任务的执行进度后,就会触发该方法

一个简单的案例:使用AsyncTask类完成一个进度条的增长处理。

1.布局文件

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

    <ProgressBar
        android:id="@+id/bar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        style="?android:attr/progressBarStyleHorizontal"
        android:visibility="visible"/>
    <TextView
        android:id="@+id/info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>


2.Activity程序

package com.wang.administrator.asynctask;

import android.app.Activity;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends Activity {
    private ProgressBar bar;
    private TextView info;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bar= (ProgressBar) findViewById(R.id.bar);
        info= (TextView) findViewById(R.id.info);

        ChildUpdate childUpdate=new ChildUpdate();
        childUpdate.execute(100);
        int x=0;
        MainActivity.this.bar.setProgress(x);
    }
    //定义一个ChildUpdate类,此类继承自AsyncTask类,目的就是进行子线程的操作,在类中分别覆写
    // 了 onPostExecute()(任务完成之后处理)、onProgressUpdate()(更新任务进度)和doInBackground()
    //,此方法中的我参数params是通过child.execute(100)调用时传递进来的,表示每次休眠0.1秒。
    private class ChildUpdate extends AsyncTask<Integer,Integer,String>{

        @Override
        protected void onPostExecute(String s) {
           MainActivity.this.info.setText(s);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
           MainActivity.this.info.setText("当前进度是:"+String.valueOf(values[0]));
        }

        @Override
        protected String doInBackground(Integer... params) {
            for(int x=0;x<100;x++){

                this.publishProgress(x);
                try {
                    Thread.sleep(params[0]);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            return "执行完毕。";
        }
    }
}


到这里为止一个简单的案例就算好了。我在练习时,因为对线程的理解不够,导致自己最开始把该放在UI主线程的程序,就是它

int x=0;
MainActivity.this.bar.setProgress(x);

放在了子线程中,导致studio一直报错:Method...must be called from UI Thread,currently inferred thread is worker。

我们也可以试着去打印Log来观察异步执行的顺序:

onPreExecute  => doInBackground => onProgressUpdate => onPostExecute

    

              

这里我多写一些东西,关于Android主线程的。

Android主线程也叫UI线程。它是非UI安全的。(也就是说非UI线程去修改UI线程会有问题)
Android中动态的修改UI线程中的UI,常用的方法有5种:

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable,long)
  • Handler
  • AsyncTask

AsyncTask注意事项:

  • 必须在UI线程中创建AsyncTask的实例(onCrete()方法中)
  • 必须在UI线程中调用AsyncTask的exceute()方法
  • 每个AsyncTask只能被执行一次

结尾:

本篇博客除了自己的理解以为,还有就是Mooc上医生的那篇视频讲学,自己总结了一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值