zoukankan      html  css  js  c++  java
  • android AsyncTask使用注意事项以及总结

    1. 1) Task的实例必须在UI thread中创建
    2) execute方法必须在UI thread中调用
    3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法
    4) 该task只能被执行一次,否则多次调用时将会出现异常。
    如果在子线程中创建调用 onPreExecute()也在创建AsyncTask的子线程中执行,doInBackground(Params...)在子线程中执行,onPostExecute(Result)和onProgressUpdate(Progress...)在主线程中


    2. AsyncTask对象不可重复使用,也就是说一个AsyncTask对象只能execute()一次,否则会有异常抛出"java.lang.IllegalStateException: Cannot execute task: the task is already running"
    AsyncTask源码如下:

    @MainThread 
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, 
    Params... params) { 
        if (mStatus != Status.PENDING) { 
            switch (mStatus) { 
            case RUNNING: 
                throw new IllegalStateException("Cannot execute task:" 
                + " the task is already running."); 
            case FINISHED: 
                throw new IllegalStateException("Cannot execute task:" 
                + " the task has already been executed " 
                + "(a task can be executed only once)"); 
        } 
    } 
    mStatus = Status.RUNNING;
    
    onPreExecute(); 
    
    
    mWorker.mParams = params; 
    exec.execute(mFuture); 
    
    
    return this; 
    }         
    

      

      

    3. 在doInBackground()中要检查isCancelled()的返回值,如果你的异步任务是可以取消的话。
    cancel()仅仅是给AsyncTask对象设置了一个标识位,当调用了cancel()后,发生的事情只有:AsyncTask对象的标识位变了,和doInBackground()执行完成后,onPostExecute()不会被回调了,
    而doInBackground()和 onProgressUpdate()还是会继续执行直到doInBackground()结束。所以要在doInBackground()中不断的检查 isCancellled()的返回值,当其返回true时就停止执行,
    特别是有循环的时候。
    public final boolean cancel(boolean mayInterruptIfRunning) {
    mCancelled.set(true);
    return mFuture.cancel(mayInterruptIfRunning);
    }
    4. 如果要在应用程序中使用网络,一定不要忘记在AndroidManifest中声明INTERNET权限,否则会报出很诡异的异常信息,比如上面的例子,如果把INTERNET权限拿掉会抛出"UnknownHostException"。
    对比Java SE的Thread
    Thread是非常原始的类,它只有一个run()方法,一旦开始,无法停止,它仅适合于一个非常独立的异步任务,也即不需要与主线程交互,对于其他情况,比如需要取消或与主线程交互,都需添加额外的代码来实现,
    并且还要注意同步的问题。而AsyncTask是封装好了的,可以直接拿来用,如果你仅执行独立的异步任务,可以仅实现doInBackground()。
    所以,当有一个非常独立的任务时,可以考虑使用Thread,其他时候,尽可能的用 AsyncTask。


    5. 通常使用AsyncTask,是通过继承这个超类来完成的,如:

    class BackgroundTask extends AsyncTask<Object,Object,Object> 
    {
        @Override
        protected Object doInBackground(Object... params) {
            return null;
        }
    }    
    

      



    子类必须重载 doInBackground方法。“<>”里面的三个类型,依次代表执行参数类型、进度参数类型和结果参数类型。doInBackground的参数类型必须是执行参数类型,返回的类型必须和结果参数类型。
    这三个类型应该根据需要来定,其实用Object也可以,用的时候在做类型转换。启动一个AsyncTask,可以在这样做:
    BackgroudTask bt = new BackgroundTask();
    bt.execute("param");
    使用AsyncTask的容易犯下的错误是在doInBackground方法里面直接对UI元素进行操作。如果需要和UI进行交互,可以配合使用publishProgress和onProgressUpdate。比如

    @Override
    protected Object doInbackground(Object... params) 
    {
        ...
        publishProgress("20%");
        ...
        publishProgress("80%");
        ...
        return null;
    }
    
    protected void onProgressUpdate(Object... progress){
        ...
        textView1.setText((String)progress[0]);
        ...
    }
    

      

    这里onProgressUpdate是工作在UI线程的。
    使用AsyncTask的另一个问题是关于cancel。实际上,单单调用AsyncTask对象的cancel方法,并不能停止doInBackground方法的继续执行。通常比较接受的方法是设置一个标志位,
    也就是在每次执行前检查一下某个变量的值(或者可以调用isCancelled方法判断),来决定继续执行还是停止。这种处理手段对于一些循环性的工作比较有用,但是对于一些循环性弱的工作可能并不怎么有效。
    这也算是AsyncTask的一个弱点。和Thread相比,AsyncTask还有一个弱点是效率的问题,这个可以在本文开头给出的链接中找到相关的信息。

    6. AsyncTask还有一个问题和onPreExecute方法有关。这个方法是工作在UI线程的。虽然是叫onPreExecute,但是doInBackground方法(也就是实际上的execute),并不会等待onPreExecute方法做完全部操作才开始执行。
    所以,一般还是不要用这个方法,可以在调用AsyncTask对象的execute方法之前就把该完成的操作完成,以免引起某些错误。
    AsyncTask还有一个方法是onPostExecute,这个方法也是工作在UI线程,它是在doInBackground方法执行结束,并返回结果后调用。这个方法里面可以调用UI线程的startActivity,这样可以实现完成大量后台操作后,
    自动跳转Activity的功能。这个方法里面也可以执行另一个AsyncTask的execute方法。

    7. 执行顺序:
    通过AsyncTask.execute()执行

    <1.6 :在1.6(Donut)之前: 在第一版的AsyncTask,任务是串行调度。一个任务执行完成另一个才能执行。由于串行执行任务,使用多个AsyncTask可能会带来有些问题。
    所以这并不是一个很好的处理异步(尤其是需要将结果作用于UI试图)操作的方法
    1.6 -- 2.3: 所有的任务并发执行,这会导致一种情况,就是其中一条任务执行出问题了,会引起其他任务出现错误.
    > 3.0 :AsyncTask又修改为了顺序执行,并且新添加了一个函数 executeOnExecutor(Executor),如果您需要并行执行,则只需要调用该函数,并把参数设置为并行执行即可。
    并行执行asyncTask.executeOnExecutor(Executors.newFixedThreadPool(7), "");

    AsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)你也可以采用这个系统提供的线程池来处理你的任务
    默认这个线程池是并发处理任务的,也就是不按顺序来.核心为5条,最大128条

  • 相关阅读:
    Centos7安装Redis-单节点
    解决物理机U盘安装Kali Linux2018.1,光驱无法加载问题
    做销售如何跟单,逼单!共20招!(转)
    销售沟通技巧(转)
    rails gem (2015-07-16)
    Foundation
    Redis TTL 为0
    Introspection反射机制
    will_paginate
    Linux下Rsync+Inotify-tools实现数据实时同步
  • 原文地址:https://www.cnblogs.com/xunzhi/p/5157733.html
Copyright © 2011-2022 走看看