美文网首页
Android AsyncTask基础知识整理

Android AsyncTask基础知识整理

作者: 呱呱_ | 来源:发表于2018-04-08 17:46 被阅读0次

    一、AsyncTask的简介

    AsyncTask是一个抽象泛型类,它是由Android封装的轻量级异步类(使用方便、代码简介),它可以在线程中执行后台任务,然后将执行的结果以及进度传递给主线程,并在主线程更新UI。

    AsyncTask内部封装了两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler)。

    • SerialExecutor 线程池用于任务的排队,让需要执行的多个耗时任务按顺序排列。
    • THREAD_POOL_EXECUTOR 线程池是真正执行任务的线程池。
    • InternalHandler 用于线程的切换,从工作线程切换到主线程。

    二、AsyncTask的泛型参数

    public abstract class AsyncTask<Params, Progress, Result> 
    
    • Params:开始异步任务时传入的参数类型,在execute()传入,跟doInBackground(Void... params)里的params类型一样。

    • Progress:执行进度,跟onProgressUpdate(Integer... values)的values类型一致,一般情况为Integer。

    • Result:执行结束的返回值,跟doInBackground返回的参数类型一致,并且跟onPostExecute的参数一致。

    如果AsyncTask确定不需要传递具体的参数,那么这三个泛型参数可以用Void代替。

    三、AsyncTask的核心方法

    onPreExecute()

    • 后台任务开始执行之前调用,在主线程调用,用来进行一些界面的初始化操作,如显示一个进度条对话框。

    doInBackground(Params...)

    • 这个方法的所有代码都在子线程中执行,我们应该在这里去处理所有的耗时操作。

    • 这个方法不可以进行UI操作,如果需要更新UI,如反馈进度,可以调用publishProgress(Progress...)方法来完成。

    onProgressUpdate(Progress...)

    • 当后台任务调用了publishProgress(Progress...)方法后,这个方法就会被调用,方法中携带的参数是后台任务传递过来的。

    • 这个方法可以对UI进行操作,在主线程中进行,可以利用参数的值对界面元素进行相应更新。

    onPostExecute(Result)

    • 当doInBackground(Params...)执行完并通过return语句进行返回时,这个方法就会被调用。

    • 返回的数据会作为参数传递到该方法中,可进行一写UI操作,提醒、关闭进度框之类的。

    上述方法执行顺序:
    onPreExecute() --> doInBackground() --> publishProgress() --> onProgressUpdate() --> onPostExecute()

    如果不需要执行更新进度,则:
    onPreExecute() --> doInBackground() --> onPostExecute()

    AsyncTask还提供了cancel(boolean)方法,用于取消异步任务,在主线程中调用。当cancel(boolean)被调用时,onPostExecute()则不被调用,将会调用onCancelled()方法。但并不是真正的取消任务,只是设置了这个任务为取消状态,我们需要在doInBackground()判断终止任务。

    四、AsyncTask的简单使用

    class DownloadTask extends AsyncTask<Void, Integer, Boolean> {  
      
        @Override  
        protected void onPreExecute() {  
            progressDialog.show();  
        }  
      
        @Override  
        protected Boolean doInBackground(Void... params) {  
            try {  
                while (true) {  
                    int downloadPercent = doDownload();  
                    publishProgress(downloadPercent);  
                    if (downloadPercent >= 100) {  
                        break;  
                    }  
                }  
            } catch (Exception e) {  
                return false;  
            }  
            return true;  
        }  
      
        @Override  
        protected void onProgressUpdate(Integer... values) {  
            progressDialog.setMessage("当前下载进度:" + values[0] + "%");  
        }  
      
        @Override  
        protected void onPostExecute(Boolean result) {  
            progressDialog.dismiss();  
            if (result) {  
                Toast.makeText(context, "下载成功", Toast.LENGTH_SHORT).show();  
            } else {  
                Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show();  
            }  
        }  
    }
    

    这里模仿下载任务,doInBackground()执行下载逻辑,onProgressUpdate()显示当前下载进度,onPostExecute()提示任务执行结果。
    如果启动任务,只需调用以下代码:

    new DownloadTask().execute();  
    

    五、AsyncTask的使用注意事项

    • 异步任务的实例必须在UI线程创建,即AsyncTask对象必须在UI线程创建。

    • execute()、cancelled()方法必须在UI线程调用。

    • 不能在doInBackground()方法中更新UI。

    • 一个任务实例只能执行一次,如果执行第二次会抛异常。

    六、AsyncTask的缺陷

    生命周期:

    • AsyncTask不与任何组件绑定生命周期,所以在Activity或者Fragment创建AsyncTask时,最好在onDestory()调用cancel(boolean)方法。总之我们要确保正确的取消AsyncTask。

    内存泄漏:

    • 如果AsyncTask被声明为Activity的非静态内部类,那么AsyncTask会保留一个对创建Activity的引用。如果Activity已经被销毁,AsyncTask还在后台执行,它将继续在内存保留这个引用,导致Activity无法被回收,引起内存泄漏。

    cancel(boolean)不一定好使:

    • 当AsyncTask已经完成,亦或其他原因不能被取消,调用cancel(boolean)并没有实际效果,还是会继续执行doInBackground()方法,只是不执行onPostExecute()。
      boolean参数mayInterruptIfRunning决定是否立即stop该Task

    结果丢失:

    • 屏幕旋转或者Activity在后台被系统杀掉等情况,会导致Activity的重新创建,之前运行的AsyncTask(非静态内部类的)会持有之前Activity的引用,但这个引用已经无效,这时调用onPostExecute()再去更新UI将不再有效。

    串行还是并行:

    • AsyncTask默认串行执行,也可以通过设置executeOnExecutor(Executor)来实现多个AsyncTask并行。

    七、AsyncTask与Handler的关系

    • 它们的关系并不大,甚至可以说不是一个层面的东西,因为AsyncTask本质是对Handler的封装,并且内部有自己维护的线程池。

    • 有一些相同的目的,都可以异步执行一些代码,避免阻塞UI线程。

    至于AsyncTask的源码理解,等以后理解了,再补上,再次留下了没技术的眼泪~
    最后奉上参考博文,毕竟东拼西凑(捂脸):
    Android中的线程状态之AsyncTask详解
    AsyncTask 使用和缺陷

    相关文章

      网友评论

          本文标题:Android AsyncTask基础知识整理

          本文链接:https://www.haomeiwen.com/subject/garmhftx.html