AsyncTask异步任务

说明

在Android中我们可以通过Thread+Handler实现多线程通信,一种经典的使用场景是:在新线程中进行耗时操作,当任务完成后通过Handler向主线程发送Message,这样主线程的Handler在收到该Message之后就可以进行更新UI的操作。上述场景中需要分别在Thread和Handler中编写代码逻辑,为了使得代码更加统一,我们可以使用AsyncTask类。

Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。首先明确Android之所以有HandlerAsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。

Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。

AsyncTask定义

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。

要使用AsyncTask工作我们要提供三个泛型参数。

AsyncTask定义了三种泛型类型 ParamsProgressResult

这里写图片描述

AsyncTask执行过程

AsyncTask有四个重要的回调方法,分别是:onPreExecute、doInBackground, onProgressUpdate 和 onPostExecute。

这里写图片描述

这里写图片描述

AsyncTask使用示例:

我们在网上获取一个网页,在一个TextView中将其源代码显示出来,并用一个ProgressBar
显示进度。

布局文件:activity.xml:

 <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="BUTTON"/>

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:progress="0"
        android:visibility="gone"/>

    <ScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
   <TextView
       android:id="@+id/textView"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:textColor="@color/colorPrimary"
       android:textSize="18sp"
       android:text="HELLO"/>
    </ScrollView>

MainActivity.java:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private String textUrl = "http://www.baidu.com";
    private ImageLoader imageLoader;
    private Button button;
    private TextView showText;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindView();
    }

    private void bindView() {
        button = (Button)this.findViewById(R.id.button);
        showText = (TextView)this.findViewById(R.id.textView);
        progressBar = (ProgressBar)this.findViewById(R.id.progressBar);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button:
                //在MainActivity中创建AsyncTask实例
                imageLoader = new ImageLoader(this,button,progressBar,showText);
                //启动异步任务,这个方法调用后,会执行AsyncTask的doInBackground()方法
                imageLoader.execute(textUrl);
                break;
        }
    }
}

自定义AsyncTask:

public class ImageLoader extends AsyncTask<String,Integer,String> {
    private static final String TAG = "ImageLoader";
    private Button button;
    private Context mContext;
    private TextView textView;
    private ProgressBar progressBar;

    public ImageLoader(Context context,Button button,ProgressBar progressBar,TextView textView){
        this.mContext = context;
        this.button = button;
        this.progressBar = progressBar;
        this.textView = textView;
    }

    //在這里我们可以对控件进行初始化操作,通常可以在该方法中显示一个进度条,从而告知用户后台任务即将开始。
    @Override
    protected void onPreExecute() {
        progressBar.setProgress(0);
        progressBar.setVisibility(View.VISIBLE);
    }

    //该方法不运行在UI线程中,主要用于异步操作,通过调用publishProgress()方法  
    //触发onProgressUpdate对UI进行操作  
    @Override
    protected String doInBackground(String... params) {
        String html = null;
        URL textUrl;
        HttpURLConnection connection = null;
        InputStream is = null;
        OutputStream os = null;
        try {
            textUrl = new URL(params[0]);
            connection = (HttpURLConnection) textUrl.openConnection();
            //要想得到文件的真实大小,必须加上这行代码
            connection.setRequestProperty("Accept-Encoding", "identity");
            is = connection.getInputStream();

            int total = connection.getContentLength();
            Log.i("Total",""+total);
            int current = 0;

            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = -1;
            while((len = is.read(buffer)) != -1)
            {
                outStream.write(buffer,0,len);
                Log.i("Fuck",""+len);
                current+=len;
                int progress = (int)((float)current/total*100);
                if (total ==0){
                    publishProgress(-1);
                }else{
                //调用AsyncTask的publishProgress(Progress…)将阶段性的处理结果发布出去,阶段性处理结果是Progress泛型类型。
                    publishProgress(progress);
                }

                Log.i(TAG,""+progress);
                Thread.sleep(1000);
            }

            html = new String(outStream.toByteArray(), "UTF-8");
            return html;

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return html;
    }

    //在doInBackground方法中,每次调用publishProgress方法都会触发该方法  
    //运行在UI线程中,可对UI控件进行操作,我们在这里进行进度的显示

    @Override
    protected void onProgressUpdate(Integer... values) {
        Log.i(TAG,""+values[0]);
        int currentProgress = values[0];
        if (currentProgress!=-1) {
            progressBar.setProgress(currentProgress);
        }
        progressBar.setProgress(values[0]);
    }

    //该方法是在主线程中被调用的。当doInBackgroud方法执行完毕后,就表示任务完成了,doInBackgroud方法的返回值就会作为参数在主线程中传入到onPostExecute方法中,这样就可以在主线程中根据任务的执行结果更新UI。
    protected void onPostExecute(String str) {
        if (str != null) {
            Log.i(TAG,"fuck");
            textView.setText(str);
            progressBar.setProgress(100);
            progressBar.setVisibility(View.GONE);
        }

    }

}

别忘记加上网络权限哦~

 <uses-permission android:name="android.permission.INTERNET"/>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值