Android AsyncTask 那些你不知道的事

 

1).Android 价值千万   java线程专题:Wait&notify&join&Yield

http://blog.csdn.net/whb20081815/article/details/65627387

2).Android 价值千万    java多线程同步 <二>Callable和Future&FutureTask

http://blog.csdn.net/whb20081815/article/details/65630694

3).Android 价值千万    java多线程<三>生产者消费者模型四种实现方法

http://blog.csdn.net/whb20081815/article/details/65635647

 4).Android 价值千万    java多线程同步 <四> synchronized&Lock&Atomic6种方式

http://blog.csdn.net/whb20081815/article/details/66971983

5).Android 价值千万java多线程同步 <五>CountDownLatch(计数器)和Semaphore(信号量)

http://blog.csdn.net/whb20081815/article/details/68498371

6).Android AsyncTask 那些你不知道的事

https://blog.csdn.net/WHB20081815/article/details/70332209

7).Android 厉害了ThreadLocal的工作原理和实例分析

https://blog.csdn.net/WHB20081815/article/details/66974651

8).Android Handle消息机制:秒懂Looper、Handler、Message三者关系

https://blog.csdn.net/WHB20081815/article/details/67639060

9).Android 性能优化<八> 多线程优化和线程管理

https://blog.csdn.net/WHB20081815/article/details/77775444

 

 

AsyncTask中的几个方法才能完成对任务的定制。经常需要去重写的方法有以下四个:

 

1. onPreExecute()

这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。

2. doInBackground(Params...)

这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回,如果AsyncTask的第三个泛型参数指定的是Void,就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。

3. onProgressUpdate(Progress...)

当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。

4. onPostExecute(Result)

当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。

 

execute = new AsyncTask<Void, Void, List<CacheContactForUI>>() {

    @Override
    protected void onPreExecute() {
        isFinish.set(true);
        loadingView.setVisibility(View.VISIBLE);
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(List<CacheContactForUI> result) {
        CXLog.d(TAG, "result-size:" + result.size());

        CacheContactItem contactItem = null;
        for (CacheContactForUI foUiList : result) {

            contactItem = foUiList.contactItem;
            if(contactItem!=null){

            ArrayList<ContactsAttrItem> phoneNumberMap = contactItem.getPhoneNumberMap();
            ArrayList<ContactsAttrItem> templistPhoneNumber = new ArrayList<ContactsAttrItem>();

            templistPhoneNumber.clear();
            for (ContactsAttrItem itemNumber : phoneNumberMap) {
                boolean added = true;
                for (ContactsAttrItem temp : templistPhoneNumber) {

                    if (itemNumber.getData().equals(temp.getData())) {
                        templistPhoneNumber.remove(itemNumber);
                        added = false;
                    } else {
                    }
                }
                if (added) {
                    templistPhoneNumber.add(itemNumber);
                    CXLog.e(TAG, "add");
                }
            }
                CXLog.e(TAG, "addAll" );
            phoneNumberMap.addAll(templistPhoneNumber);
            contactItem.setPhoneNumberMap(templistPhoneNumber);
                foUiList.setContactItem(contactItem);


            }
        }


        mAdapter.setContactForUIsList(result);
        mergeContactsList.setAdapter(mAdapter);
        mAdapter.notifyDataSetChanged();
        loadingView.setVisibility(View.GONE);
        isFinish.set(false);
    }

    @Override
    protected List<CacheContactForUI> doInBackground(Void... params) {
        //isFinish.set(true);
        //loadingView.setVisibility(View.VISIBLE);
        return initData(itemId);
    }

    ;
}.execute();

 

public AsyncTask() {
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true);

            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            //noinspection unchecked
            Result result = doInBackground(mParams);
            Binder.flushPendingCommands();
            return postResult(result);
        }
    };

    mFuture = new FutureTask<Result>(mWorker) {
        @Override
        protected void done() {
            try {
                postResultIfNotInvoked(get());
            } catch (InterruptedException e) {
                android.util.Log.w(LOG_TAG, e);
            } catch (ExecutionException e) {
                throw new RuntimeException("An error occurred while executing doInBackground()",
                        e.getCause());
            } catch (CancellationException e) {
                postResultIfNotInvoked(null);
            }
        }
    };
}

 

3.0以前

  1. private static final int CORE_POOL_SIZE = 5;  
  2. private static final int MAXIMUM_POOL_SIZE = 128;  
  3. private static final int KEEP_ALIVE = 10;  
  4. ……  
  5. private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,  
  6.         MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);  

3.0以后

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// 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 int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;

 

 

源码分析:

   用到很多线程的知识:Executor,FutureTask,AtomicBoolean,ThreadPoolExecutor,BlockingQueue

总结:并行还是串行

      在Android 1.6之前的版本,AsyncTask是串行的,在1.6至2.3的版本,改成了并行的。在2.3之后的版本又做了修改,可以支持并行和串行,当想要串行执行时,直接执行execute()方法,如果需要并行执行,则要执行executeOnExecutor(Executor)。

 

记得以前有个面试题经常会问道:AsyncTask运行的原理是什么?有什么缺陷?

以前对于缺陷的答案可能是:AsyncTask在并发执行多个任务时发生异常。其实还是存在的,在3.0以前的系统中还是会以支持多线程并发的方式执行,支持并发数也是我们上面所计算的128,阻塞队列可以存放10个;也就是同时执行138个任务是没有问题的;而超过138会马上出现

 

 

如果我们想要并行执行任务,可以调用AsyncTask的executeOnExecutor方法。如下:

new AsyncTask<Void,Void,Void>(){

    @Override
    protected Void doInBackground(Void... params) {
        return null;
    }

}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其实很好理解的。直接执行executeOnExecutor方法,传入AsyncTask.THREAD_POOL_EXECUTOR线程池。这样就绕过了SerialExecutor任务排队的过程。

 

AsyncTask内存泄漏问题;非静态内部类持有外部类的引用

 

AsyncTask可能存在新开大量线程消耗系统资源和导致应用FC的风险,因此,我们需要根据自己的需求自定义不同的线程池,由于篇幅问题,将留到下篇再讲。

  • AsyncTask不是被设计为处理耗时操作的,耗时上限为几秒钟,如果要做长耗时操作,强烈建议你使用Executor,ThreadPoolExecutor以及FutureTask

 

AsyncTask原理:

AnsycTask执行任务时,内部会创建一个进程作用域的线程池来管理要运行的任务,

也就就是说当你调用了AsyncTask.execute()后,AsyncTask会把任务交给线程池,

由线程池来管理创建Thread和运行Therad。最后和UI打交道就交给Handler去处理了。

 

问题:

“你在项目中,会用什么方案来替换AsyncTask呢?

 

 

http://blog.csdn.net/guolin_blog/article/details/11711405

 

http://blog.csdn.net/lmj623565791/article/details/38614699

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值