Android之AsyncTask的使用

Android之AsyncTask的使用

为了解决新线程不能更新UI组件的问题,Android提供了如下几种解决方案
1.使用Handler实现线程间的通信
2.Activity.runOnUiThread(Runnable)
3.View.post()
4.View.postDelayed(Runnable,long)

这几种方式有时候会导致编程显得繁琐,而异步任务(AsyncTask)可以进一步
简化操作,不需要借助额外的hanlder即可实现。当我们通过线程执行耗时任务,并且在执行完任务以后可能会对UI进行更新,一般我们都会使用Handler来更新UI,但是如果多个任务同时执行时则会显得代码臃肿,Anroid提供了AsyncTask,他使得异步任务实现起来更加简单,代码简洁。

public abstract class AsyncTask<Params, Progress, Result> {}

AsyncTack是一个抽象的泛类型,通常被用来继承,它有三个泛型参数分别是Params,Progress,Result

  • Params:指定任务执行的输入参数的类型
  • Progress:是后台任务完成得进度值的类型
  • Result:执行完成任务后返回结果的类型。

如果不需要某个参数,可以设置为void。

AsyncTask中的四个核心方法:

  • 1.onPreExecute():在主线程中执行,一般在任务执行前做准备工作,比如对
    UI进行一些标记。如初始化控件的一些参数。
  • 2.doInBackground(Params…params):在线程池中执行,在onPreExecute()方法执行完
    以后运行,用来完成角为耗时的操作,在执行过程中可以调用publishProgress(Progress…values)
    来更新进度的信息
  • 3.onProgressUpdate(Progress values):在主线程中执行,当调用publishProgress(Progress values)时,此方法会将进度更新到UI组件上。
  • 4.onPostExecute():在主线程中执行,当后台任务执行完毕以后,他会被执行
    doInBackground方法得到的结果就是返回的result的值,此方法一般做任务执行
    后的首尾工作,比如更新UI和数据。

重写上述几个方法后,调用AsyncTack子类的实例的execute()方法开始执行耗时任务
使用AsyncTask时必须遵循下列规则:

  • 1.必须在UI线程中创建AsyncTask
  • 2.必须在UI线程中调用AsyncTask的execute()方法
  • 3.AsyncTask的onPreEcexute(),onPostExecute()等几个方法不应该由程序员代码调用
    而应该由系统调用
  • 4.每个AsyncTask只能被调用一次,多次调用会引发异常

使用AsyncTask执行下载任务的demo,布局代码如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    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=".Activity.AsyncTaskActivity">
    <ProgressBar
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:id="@+id/progressbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
<TextView
    android:text="下载内容"
    android:id="@+id/show"
    android:textSize="18sp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
    <Button
        android:id="@+id/id_btn"
        android:textSize="18sp"
        android:text="开始下载"
        android:onClick="downLoad"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

java代码如下:


import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.example.yang.toolbar.R;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class AsyncTaskActivity extends AppCompatActivity {
private TextView show;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task);
        show=findViewById(R.id.show);
    }

    public void downLoad(View view) throws MalformedURLException {
           DownLoad task=new DownLoad(this, (ProgressBar) findViewById(R.id.progressbar));
           task.execute(new URL("http://www.baidu.com"));
    }
    class DownLoad extends AsyncTask<URL,Integer,String>{
        private ProgressBar progressBar;
        int hasRead=0;
        Context context;
        //构造函数如下
        public DownLoad(Context context,ProgressBar progressBar){
            this.context=context;
            this.progressBar=progressBar;
        }
        //点击后首先执行onPreExecute()进行准备工作,控件的初始化等,第二步执行doInBackGround()方法,
        //在该方法内调用了publishProgress()方法来更新任务的执行进度
        //调用publishProgress()会触发onProgressUpdate完成对UI进度条的更新
        //当doInBackground()方法完成后,系统会自动调用onPostExecute()方法,并将doInBackground()方法的返回值
        //传递给该方法
        @Override
        protected String doInBackground(URL... urls) {
            StringBuilder builder=new StringBuilder();
            try{
                //获取输入流
                URLConnection conn=urls[0].openConnection();
                BufferedReader br=new BufferedReader(new InputStreamReader(
                        conn.getInputStream(),"utf-8"));
                String line=null;
                //读数据
                while ((line=br.readLine())!=null){
                    builder.append(line+"\n");
                    hasRead++;
                    publishProgress(hasRead);
                    //更新UI
                }
                //返回数据
                return builder.toString();
            }catch (Exception e){
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String s) {
           //什么时候被调用?当在doInBackground中调用publishProgress时调用
            show.setText(s);
            progressBar.setVisibility(View.INVISIBLE);
        }

        @Override
        protected void onPreExecute() {
            //给UI控件设置参数等一些工作
            progressBar.setVisibility(View.VISIBLE);
            progressBar.setProgress(0);
            progressBar.setMax(120);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
           show.setText("已经读取了【"+values[0]+"】行!");
           progressBar.setProgress(values[0]);
        }
    }
}








代码的执行流程

1.点击后首先执行onPreExecute()准备工作控件的初始化等,第二步执行doInBackGround()方法。
2.在该方法内调用了publishProgress()方法来更新任务的执行进度。
3.调用publishProgress()会触发onProgressUpdate完成对UI进度条的更新。
4.当doInBackground()方法完成后,系统会自动调用onPostExecute()方法,并将doInBackground()方法的返回值传递给该方法。

本来打算写AsyncTask原理的,看完书发现自己不知道如何描述,原理也比较复杂,还不能很好的阐述原理,等深入了解原理以后再做更新

发布了123 篇原创文章 · 获赞 74 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43927892/article/details/101106111