Android AsyncTask 那些你不知道的事
来源:互联网 发布:maxwell软件下载 编辑:程序博客网 时间:2024/05/29 04:47
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); } } };}
- private static final int CORE_POOL_SIZE = 5;
- private static final int MAXIMUM_POOL_SIZE = 128;
- private static final int KEEP_ALIVE = 10;
- ……
- private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
- MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
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 workprivate 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;
总结:并行还是串行
在Android 1.6之前的版本,AsyncTask是串行的,在1.6至2.3的版本,改成了并行的。在2.3之后的版本又做了修改,可以支持并行和串行,当想要串行执行时,直接执行execute()方法,如果需要并行执行,则要执行executeOnExecutor(Executor)。
记得以前有个面试题经常会问道:AsyncTask运行的原理是什么?有什么缺陷?
以前对于缺陷的答案可能是:AsyncTask在并发执行多个任务时发生异常。其实还是存在的,在3.0以前的系统中还是会以支持多线程并发的方式执行,支持并发数也是我们上面所计算的128,阻塞队列可以存放10个;也就是同时执行138个任务是没有问题的;而超过138会马上出现
如果我们想要并行执行任务,可以调用AsyncTask的executeOnExecutor方法。如下:
- 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可能存在新开大量线程消耗系统资源和导致应用FC的风险,因此,我们需要根据自己的需求自定义不同的线程池,由于篇幅问题,将留到下篇再讲。
- AsyncTask不是被设计为处理耗时操作的,耗时上限为几秒钟,如果要做长耗时操作,强烈建议你使用Executor,ThreadPoolExecutor以及FutureTask
- Android AsyncTask 那些你不知道的事
- Android开发中那些你不知道的事
- Android Context 你不知道的那些事
- 那些你不知道的事......
- IOCP你不知道的那些事
- UIResponder那些你不知道的事
- editplus - 你不知道的那些事
- 虚拟主机,你那些不知道的事
- 字符串,那些你不知道的事
- 搜索引擎那些你不知道的事
- [Android] 你所不知道的drawable的那些细节
- Android 那些你所不知道的Bitmap对象详解
- Android 那些你所不知道的Bitmap对象详解
- Android 那些你所不知道的Bitmap对象详解
- Android 那些你所不知道的Bitmap对象详解
- Android 那些你所不知道的Bitmap对象详解
- Android 那些你所不知道的Bitmap对象详解
- Android 那些你所不知道的Bitmap对象详解
- foj 2173 (floyd+矩阵快速幂 )
- ASP.NET DEV 前端利用后端方法显示PDF文件链接地址,点击下载
- iOS引导页,可选是视频或者是图片swift版
- 微信小程序(2)-小程序信息完善以及开发前准备,代码审核与发布
- Spring4.1.6常用注解
- Android AsyncTask 那些你不知道的事
- java.lang.IllegalStateException: The specified child already has a parent.
- Linux驱动开发常用调试工具---之内存读写工具devmem和devkmem
- 利用mybatis-generator自动生成代码
- RK3288开发过程中遇到的问题点和解决方法
- 【Android】getActionBar()为null的解决方法总结
- php7 中的 Immutable数组 与 非Immutable数组
- 光波波长划分和无线电波频段划分
- 悼念512汶川大地震遇难同胞 (sdut oj)