Android线程(2)——AsyncTask

       在上一篇中,我们简单的介绍了HandlerThread,我们了解到其是一种特殊的与Handler结合使用的一种Thread。今天我们来学习一下Android线程中的另一个知识点AsyncTask,这个词直译过来是异步任务的意思,首先先看一下这个类的官方介绍


AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called begin, doInBackground, processProgress and end.


大概意思是:异步任务能够让我们简单准确的使用UI线程,它可以运行在后台并把最终的运行结果回传给UI线程,整个过程不需要借助(管理)其他的线程或者Handler。

异步任务运行在后台,运行结果回传给UI线程。一个异步任务可以通过三个名为Params,Progress和Result的泛型以及begin,doInBackground,processProgress以及end四步来定义。


到这里,我们对其有一个基本的了解了,总结一句话:其创建的异步任务在后台线程执行,最终的执行结果会回传给UI线程。

 

下面只需要看其如何实现这个目标的即可。

AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)

Here is an example of subclassing:

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }
 Once created, a task is executed very simply:

 new DownloadFilesTask().execute(url1, url2, url3);
 AsyncTask's generic types
The three types used by an asynchronous task are the following:

Params, the type of the parameters sent to the task upon execution. 
Progress, the type of the progress units published during the background computation. 
Result, the type of the result of the background computation. 
Not all types are always used by am asynchronous task. To mark a type as unused, simply use the type Void:

 private class MyTask extends AsyncTask

AsyncTask是一个抽象类,所以其必须被子类化了之后才能实例化使用,通常其子类必须重写doInBackground(),通常还需要重写onPostExecute()。关于三个泛型参数的说明也很详细:

  • Params:发送给即将要执行的异步任务的参数
  • Progress:执行的进度,后台运行
  • Result:后台任务的运行结果

如果其中有的参数没有用到,直接用Void代替即可

上面说到执行一个异步任务通常有四步,下面就来看看这四步的具体实现:

The 4 steps
 When an asynchronous task is executed, the task goes through 4 steps:
 
     onPreExecute(), invoked on the UI thread immediately after the task
     is executed. This step is normally used to setup the task, for instance by
     showing a progress bar in the user interface.

     doInBackground(Params...), invoked on the background thread
     immediately after onPreExecute() finishes executing. This step is used
     to perform background computation that can take a long time. The parameters
     of the asynchronous task are passed to this step. The result of the computation must
     be returned by this step and will be passed back to the last step. This step
     can also use publishProgress(Progress...) to publish one or more units
     of progress. These values are published on the UI thread, in the
     onProgressUpdate(Progress...) step.

     onProgressUpdate(Progress...), invoked on the UI thread after a
     call to publishProgress(Progress...). The timing of the execution is
     undefined. This method is used to display any form of progress in the user
     interface while the background computation is still executing. For instance,
     it can be used to animate a progress bar or show logs in a text field.

     onPostExecute(Result), invoked on the UI thread after the background
     computation finishes. The result of the background computation is passed to
     this step as a parameter.
  • onPreExecute():运行在UI线程,通常用于在异步任务执行前触发界面进度view显示
  • doInBackground():运行在后台线程,主要用于计算任务执行进度,可以通过publishProgress()(本质还是调用onProgressUpdate())实现进度在UI界面的实时显示
  • onProgressUpdate():当publishProgress()被调用的时候其会执行(在UI线程)
  • onPostExecute():当异步任务执行完成后,计算结果会通过result参数回传过来,因为其运行在UI线程,所以运行结果就被传递到了UI线程。

 

        下面就来结合具体的实例来看一下使用,下面就以API给的例子扩展一下,来实现通过异步任务实现下载并在界面实时显示进度的这样一个效果。主要代码如下:

自定义异步任务代码:

package aoto.com.operationasynctask;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Text;

/**
 * author:why
 * created on: 2019/4/15 19:47
 * description:
 */
public class DownloadFilesTask extends AsyncTask<Integer, Integer, Long> {

    private static final String TAG = "DownloadFilesTaskWhy";
    private ProgressBar progressBar;
    private TextView textView;
    private Context context;
    int progress=0;

    public DownloadFilesTask(Context context,ProgressBar progressBar,TextView textView) {
        this.progressBar = progressBar;
        this.context=context;
        this.textView=textView;
    }

    @Override
    protected Long doInBackground(Integer... voids) {

        while(progress<50){
            publishProgress((progress+1));
            try {
                Thread.sleep(100);
                progress++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return Long.valueOf(100);
    }


    @Override
    protected void onProgressUpdate(Integer... values) {
        Log.e(TAG, "onProgressUpdate: " );
        progressBar.setProgress(values[0]);
        textView.setText("已下载:"+values[0]*2+"%");
    }

    @Override
    protected void onPostExecute(Long aLong) {
        Log.e(TAG, "onPostExecute: " );
        Toast.makeText(context,"下载完成",Toast.LENGTH_SHORT).show();
    }

}

测试代码:

package aoto.com.operationasynctask;

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

/**
 * @author why
 * @date 2019-4-15 19:43:24
 */
public class MainActivity extends AppCompatActivity {

    DownloadFilesTask task;
    ProgressBar progressBar;
    TextView progressText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        progressBar=findViewById(R.id.download_progress_graphic);
        progressText=findViewById(R.id.download_progress_digital);

        task=new DownloadFilesTask(this,progressBar,progressText);
    }


    /**
     * 模拟执行下载文件
     * @param view
     */
    public void download(View view){
        task.execute();
    }

}

AsyncTask本身维护着一个线程池,大小在2-4之间。有一个长度为128的任务队列...里面的很多内容可以之间在该类中查看到

 // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work


 private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

........

具体的使用还是结合文档较好。

注:欢迎扫码关注

利用 TensorFlow 训练自己的目标识别器。本文内容来自于我的毕业设计,基于 TensorFlow 1.15.0,其他 TensorFlow 版本运行可能存在问题。.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值