Android AsyncTask的使用及泛式参数

Android中我们可以通过Theater+Handler来实现多线程通信,当子线程的耗时任务完成后通过Handler向主线程发送message,主线程收到message后开始更新UI,而为了使代码更加统一,我们会使用AsyncTask类。

  1. 什么是AsyncTask
  2. AsyncTask怎么用
  3. 需要实现的几个方法、这些方法有什么用
  4. 泛型参数
  5. 长度可变的泛式参数
  6. 案例–倒计时Demo

什么是AsyncTask

  1. AsyncTask是Android提供的轻量级异步类。
  2. 为了降低异步通信的开发难度,提供了AsyncTask。
  3. AsyncTask直接继承与Object类,位于android.os包中。
  4. 使用AsyncTask可以忽略Looper、MessageQueue、Handler等复杂对象,更便捷地完成耗时操作。

AsyncTask的使用

  1. 新建内部类继承AsyncTask
  2. 定义AsyncTask的三种泛型参数
  3. 重写doInBackground抽象方法
  4. 重写onPreExecute方法
  5. 重写onProgressUpdate方法
  6. 重写onPostExecute方法
  7. 在需要启动的地方调用execute方法

需要实现的几个方法及作用

AsyncTask有四种重要的回调方法

  • onProgressUpdate
  • doInBackground
  • onPostExecute
  • onPreExecute
    这四个方法会在AsyncTask的不同时期进行自动调用,我们只需要实现这几个方法的内部逻辑即可。这四个方法的一些参数和返回值都是基于泛型的,而且泛型的类型还不一样,所以在AsyncTask的使用中会遇到三种泛型参数:Params, Progress 和 Result,如下图所示:
    这里写图片描述
    Params表示用于AsyncTask执行任务的参数的类型
    Progress表示在后台线程处理的过程中,可以阶段性地发布结果的数据类型
    Result表示任务全部完成后所返回的数据类型
    我们通过调用AsyncTask的execute()方法传入参数并执行任务,然后AsyncTask会依次调用以下四个方法:
  • onPreExecute
    这里写图片描述
  • doInBackground
    这里写图片描述
  • onProgressUpdate
    这里写图片描述
  • onPostExecute
    这里写图片描述
    下面截取Android中AsyncTask使用详解中的例子
    布局文件
"http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    

java:

public class MainActivity extends Activity implements Button.OnClickListener {

    TextView textView = null;
    Button btnDownload = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView)findViewById(R.id.textView);
        btnDownload = (Button)findViewById(R.id.btnDownload);
        Log.i("iSpring", "MainActivity -> onCreate, Thread name: " + Thread.currentThread().getName());
    }

    @Override
    public void onClick(View v) {
        //要下载的文件地址
        String[] urls = {
                "http://blog.csdn.net/iispring/article/details/47115879",
                "http://blog.csdn.net/iispring/article/details/47180325",
                "http://blog.csdn.net/iispring/article/details/47300819",
                "http://blog.csdn.net/iispring/article/details/47320407",
                "http://blog.csdn.net/iispring/article/details/47622705"
        };

        DownloadTask downloadTask = new DownloadTask();
        downloadTask.execute(urls);
    }

    //public abstract class AsyncTask
    //在此例中,Params泛型是String类型,Progress泛型是Object类型,Result泛型是Long类型
    private class DownloadTask extends AsyncTask<String, Object, Long> {
        @Override
        protected void onPreExecute() {
            Log.i("iSpring", "DownloadTask -> onPreExecute, Thread name: " + Thread.currentThread().getName());
            super.onPreExecute();
            btnDownload.setEnabled(false);
            textView.setText("开始下载...");
        }

        @Override
        protected Long doInBackground(String... params) {
            Log.i("iSpring", "DownloadTask -> doInBackground, Thread name: " + Thread.currentThread().getName());
            //totalByte表示所有下载的文件的总字节数
            long totalByte = 0;
            //params是一个String数组
            for(String url: params){
                //遍历Url数组,依次下载对应的文件
                Object[] result = downloadSingleFile(url);
                int byteCount = (int)result[0];
                totalByte += byteCount;
                //在下载完一个文件之后,我们就把阶段性的处理结果发布出去
                publishProgress(result);
                //如果AsyncTask被调用了cancel()方法,那么任务取消,跳出for循环
                if(isCancelled()){
                    break;
                }
            }
            //将总共下载的字节数作为结果返回
            return totalByte;
        }

        //下载文件后返回一个Object数组:下载文件的字节数以及下载的博客的名字
        private Object[] downloadSingleFile(String str){
            Object[] result = new Object[2];
            int byteCount = 0;
            String blogName = "";
            HttpURLConnection conn = null;
            try{
                URL url = new URL(str);
                conn = (HttpURLConnection)url.openConnection();
                InputStream is = conn.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buf = new byte[1024];
                int length = -1;
                while ((length = is.read(buf)) != -1) {
                    baos.write(buf, 0, length);
                    byteCount += length;
                }
                String respone = new String(baos.toByteArray(), "utf-8");
                int startIndex = respone.indexOf(""</span>);
                <span class="hljs-keyword">if</span>(startIndex > <span class="hljs-number">0</span>){
                    startIndex += <span class="hljs-number">7</span>;
                    <span class="hljs-keyword">int</span> endIndex = respone.indexOf(<span class="hljs-string">"");
                    if(endIndex > startIndex){
                        //解析出博客中的标题
                        blogName = respone.substring(startIndex, endIndex);
                    }
                }
            }catch(MalformedURLException e){
                e.printStackTrace();
            }catch(IOException e){
                e.printStackTrace();
            }finally {
                if(conn != null){
                    conn.disconnect();
                }
            }
            result[0] = byteCount;
            result[1] = blogName;
            return result;
        }

        @Override
        protected void onProgressUpdate(Object... values) {
            Log.i("iSpring", "DownloadTask -> onProgressUpdate, Thread name: " + Thread.currentThread().getName());
            super.onProgressUpdate(values);
            int byteCount = (int)values[0];
            String blogName = (String)values[1];
            String text = textView.getText().toString();
            text += "\n博客《" + blogName + "》下载完成,共" + byteCount + "字节";
            textView.setText(text);
        }

        @Override
        protected void onPostExecute(Long aLong) {
            Log.i("iSpring", "DownloadTask -> onPostExecute, Thread name: " + Thread.currentThread().getName());
            super.onPostExecute(aLong);
            String text = textView.getText().toString();
            text += "\n全部下载完成,总共下载了" + aLong + "个字节";
            textView.setText(text);
            btnDownload.setEnabled(true);
        }

        @Override
        protected void onCancelled() {
            Log.i("iSpring", "DownloadTask -> onCancelled, Thread name: " + Thread.currentThread().getName());
            super.onCancelled();
            textView.setText("取消下载");
            btnDownload.setEnabled(true);
        }
    }
}

这里写图片描述

泛型参数

AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。
- Params 启动任务执行的输入参数,比如HTTP请求的URL。
- Progress 后台任务执行的百分比。
- Result 后台执行任务最终返回的结果,比如String,Integer等。

长度可变的泛型参数

可输入多种参数

protected void onProgressUpdate(String... values)

案例-Demo倒计时

java:
public class Main2Activity extends AppCompatActivity {
    private TextView tv1;
    private Button button;
    int time = 10;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        bindID();
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new DownloadTask().execute();
            }
        });
    }

    private void bindID() {
        button = findViewById(R.id.btn);
        tv1 = findViewById(R.id.tv);

    }


    class DownloadTask extends AsyncTask {

        @Override
        protected String doInBackground(String... strings) {
            while (time > 0) {
                publishProgress(time + "");
                time--;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return "下载完成";

        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            tv1.setText(values[0]);
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            tv1.setText(s);
        }
    }

}

xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Main2Activity"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="button"/>
    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

LinearLayout>

你可能感兴趣的:(Android AsyncTask的使用及泛式参数)