• android多线程


    package com.example.administrator.knowledgebase;

    import android.os.AsyncTask;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;

    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;

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

    AsyncTask是Android提供的一个助手类,它对Thread和Handler进行了封装,方便我们使用。Android之所以提供AsyncTask这个类,就是为了方便我们在后台线程中执行操作,然后将结果发送给主线程,从而在主线程中进行UI更新等操作。在使用AsyncTask时,我们无需关注Thread和Handler,AsyncTask内部会对其进行管理,这样我们就只需要关注于我们的业务逻辑即可。

    AsyncTask有四个重要的回调方法,分别是:onPreExecute、doInBackground, onProgressUpdate 和 onPostExecute。这四个方法会在AsyncTask的不同时期进行自动调用,我们只需要实现这几个方法的内部逻辑即可。这四个方法的一些参数和返回值都是基于泛型的,而且泛型的类型还不一样,所以在AsyncTask的使用中会遇到三种泛型参数:Params, Progress 和 Result,
    */
    public class AsyncTaskActivity extends AppCompatActivity {

    private Button downLoadBtn;

    private TextView tv5;

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

    downLoadBtn=(Button) findViewById(R.id.button6);
    tv5=(TextView)findViewById(R.id.textView5);

    downLoadBtn.setOnClickListener(new View.OnClickListener() {
    @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, Progress, Result>
    * Params表示用于AsyncTask执行任务的参数的类型
    Progress表示在后台线程处理的过程中,可以阶段性地发布结果的数据类型
    Result表示任务全部完成后所返回的数据类型
    * 在此例中,Params泛型是String类型,Progress泛型是Object类型,Result泛型是Long类型
    */
    private class DownloadTask extends AsyncTask<String,Object,Long>{

    /**
    * 该方法有MainThread注解,表示该方法是运行在主线程中的。
    * 在AsyncTask执行了execute()方法后就会在UI线程上执行onPreExecute()方法,
    * 该方法在task真正执行前运行,我们通常可以在该方法中显示一个进度条,
    * 从而告知用户后台任务即将开始。
    */
    @Override
    protected void onPreExecute() {
    super.onPreExecute();
    //按钮不可点击状态
    downLoadBtn.setEnabled(false);

    tv5.setText("开始下载........");

    }

    /**
    * 该方法有WorkerThread注解,表示该方法是运行在单独的工作线程中的,
    * 而不是运行在主线程中。doInBackground会在onPreExecute()方法执行完成后立即执行,
    * 该方法用于在工作线程中执行耗时任务,我们可以在该方法中编写我们需要在后台线程中运行的逻辑代码,
    * 由于是运行在工作线程中,所以该方法不会阻塞UI线程。该方法接收Params泛型参数,参数params是Params类型的不定长数组,
    * 该方法的返回值是Result泛型,由于doInBackgroud是抽象方法,我们在使用AsyncTask时必须重写该方法。
    * 在doInBackground中执行的任务可能要分解为好多步骤,每完成一步我们就可以通过调用AsyncTask的publishProgress(Progress…)将阶段性的处理结果发布出去,
    * 阶段性处理结果是Progress泛型类型。当调用了publishProgress方法后,处理结果会被传递到UI线程中,并在UI线程中回调onProgressUpdate方法,
    * 下面会详细介绍。根据我们的具体需要,我们可以在doInBackground中不调用publishProgress方法,当然也可以在该方法中多次调用publishProgress方法。
    * doInBackgroud方法的返回值表示后台线程完成任务之后的结果。
    * @param params
    * @return
    */
    @Override
    protected Long doInBackground(String... params) {
    //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("<title>");
    if(startIndex > 0){
    startIndex += 7;
    int endIndex = respone.indexOf("</title>");
    if(endIndex > startIndex){
    //解析出博客中的标题
    blogName = respone.substring(startIndex, endIndex);
    }
    }
    }catch(Exception e){
    e.printStackTrace();
    }finally {
    if(conn != null){
    conn.disconnect();
    }
    }
    result[0] = byteCount;
    result[1] = blogName;
    return result;
    }


    /**
    * 上面我们知道,当我们在doInBackground中调用publishProgress(Progress…)方法后,就会在UI线程上回调onProgressUpdate方法,
    * 该方法也具有MainThread注解,表示该方法是在主线程上被调用的,且传入的参数是Progress泛型定义的不定长数组。
    * 如果在doInBackground中多次调用了publishProgress方法,那么主线程就会多次回调onProgressUpdate方法。
    *
    *
    * @param values
    */
    @Override
    protected void onProgressUpdate(Object... values) {
    super.onProgressUpdate(values);

    int byteCount = (int)values[0];
    String blogName = (String)values[1];
    String text = tv5.getText().toString();
    text += " 博客《" + blogName + "》下载完成,共" + byteCount + "字节";
    tv5.setText(text);

    }

    /**
    * 该方法也具有MainThread注解,表示该方法是在主线程中被调用的。
    * 当doInBackgroud方法执行完毕后,就表示任务完成了,doInBackgroud方法的返回值就会作为参数在主线程中传入到onPostExecute方法中,
    * 这样就可以在主线程中根据任务的执行结果更新UI。
    *
    *
    * @param aLong
    */
    @Override
    protected void onPostExecute(Long aLong) {
    super.onPostExecute(aLong);

    String text = tv5.getText().toString();
    text += " 全部下载完成,总共下载了" + aLong + "个字节";
    tv5.setText(text);
    downLoadBtn.setEnabled(true);


    }

    @Override
    protected void onCancelled() {
    super.onCancelled();
    tv5.setText("取消下载");
    downLoadBtn.setEnabled(true);
    }
    }

    }

  • 相关阅读:
    Nth Highest Salary
    第二高的薪水
    组合两个表
    牛客(66)机器人的运动范围
    牛客(65)矩阵中的路径
    牛客(64)滑动窗口的最大值
    牛客(63)数据流中的中位数
    牛客(62)二叉搜索树的第k个结点
    牛客(61)序列化二叉树
    mybits(2)增删改查
  • 原文地址:https://www.cnblogs.com/zimo-bwl1029-s/p/7892575.html
Copyright © 2020-2023  润新知