Android5.0 AsyncTask的实现分析
来源:互联网 发布:我国网络零售的特点 编辑:程序博客网 时间:2024/06/05 06:25
首先看一下AsyncTask在Android中的一个简单应用:
package com.example.zhy_asynctask_demo01; import android.app.Activity; import android.app.ProgressDialog; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.widget.TextView; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private ProgressDialog mDialog; private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.id_tv); mDialog = new ProgressDialog(this); mDialog.setMax(100); mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mDialog.setCancelable(false); new MyAsyncTask().execute(); } private class MyAsyncTask extends AsyncTask<Void, Integer, Void> { @Override protected void onPreExecute() { mDialog.show(); Log.e(TAG, Thread.currentThread().getName() + " onPreExecute "); } @Override protected Void doInBackground(Void... params) { // 模拟数据的加载,耗时的任务 for (int i = 0; i < 100; i++) { try { Thread.sleep(80); } catch (InterruptedException e) { e.printStackTrace(); } publishProgress(i); } Log.e(TAG, Thread.currentThread().getName() + " doInBackground "); return null; } @Override protected void onProgressUpdate(Integer... values) { mDialog.setProgress(values[0]); Log.e(TAG, Thread.currentThread().getName() + " onProgressUpdate "); } @Override protected void onPostExecute(Void result) { // 进行数据加载完成后的UI操作 mDialog.dismiss(); mTextView.setText("LOAD DATA SUCCESS "); Log.e(TAG, Thread.currentThread().getName() + " onPostExecute "); } } }
在这个简单的Demo中我们可以看到 AsyncTask的入口在:
new MyAsyncTask().execute();
进入到源码中我们看下execute()方法:
public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
在函数中又调用了executeOnExecutor方法:
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; }
方法中根据一个枚举来判定AsyncTask的当前的状态:
public enum Status { /** * Indicates that the task has not been executed yet. */ PENDING, /** * Indicates that the task is running. */ RUNNING, /** * Indicates that {@link AsyncTask#onPostExecute} has finished. */ FINISHED, }
- PENDING:还未执行过executed
- RUNNING:正在执行过程中
- FINISHED:已经结束
在executeOnExecutor中每个异步任务在完成前只能执行一次,通过上述的枚举类型中的状态实现,随后调用的是onPreExecute()方法:
protected void onPreExecute() { }
这里还是在主线程中,我们可以重写这个方法,做一些开始异步操作前的一些准备动作。
执行完成后:
mWorker.mParams = params;
在Asytask中有两个重要的成员变量:
private final WorkerRunnable<Params, Result> mWorker; private final FutureTask<Result> mFuture;
我们可以将这里的mWorker 视为一个Runable接口 这里将参数Parameter 传入到mWorker 中
接下来执行:
exec.execute(mFuture);
我们研究下这里的exec 变量:
它的传入参数是一个成员变量: sDefaultExecutor 来看下如何定义的:
private static class SerialExecutor implements Executor { final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); Runnable mActive; public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { THREAD_POOL_EXECUTOR.execute(mActive); } } }
最终先开始调用的excute方法就是执行这个内部类中的excute方法:
这个方法同时也是AsyTask的精髓:
在内部类中有一个成员变量:
final ArrayDeque<Runnable> mTasks
我们介绍下这个:
1)ArrayDeque有两个类属性,head和tail,两个指针。
2)ArrayDeque通过一个数组作为载体,其中的数组元素在add等方法执行时不移动,发生变化的只是head和tail指针,而且指针是循环变化,数组容量不限制。
3)offer方法和add方法都是通过其中的addLast方法实现,每添加一个元素,就把元素加到数组的尾部,此时,head指针没有变化,而tail指针加一,因为指针是循环加的,所以当tail追上head((this.tail = this.tail + 1 & this.elements.length - 1) == this.head)时,数组容量翻一倍,继续执行。
4)remove方法和poll方法都是通过其中的pollFirst方法实现,每移除一个元素,该元素所在位置变成null,此时,tail指针没有变化,而head指针加一,当数组中没有数据时,返回null。
5)因为ArrayDeque不是线程安全的,所以,用作堆栈时快于 Stack,在用作队列时快于 LinkedList。
其实说明白了它就是一个队列,里面的offer 方法就是将请求缓存起来,poll方法用来获取一个请求,我们知道在之前的版本中AsyTask被人诟病的就是当请求数超过128后 会抛出异常,但是在新版本的AsyTask中我们用队列将请求缓存后便不存在这种风险,实际上最终excute方法会调用到的方法是 mFuture中的run方法:
public void run() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }
方法中我们可以看到最终是调用到的callable 的call方法这里的callable就是两个重要的成员变量的第二个:mWorker中的call:
public Result call() throws Exception { mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //noinspection unchecked return postResult(doInBackground(mParams)); }
这里调用到了doInBackground(mParams) 进行耗时操作
其实总结起来AsyTask就是线程池和Handler的一个封装
- Android5.0 AsyncTask的实现分析
- 从源码上,分析AsyncTask的实现
- RecentsTask分析Android5.0
- Asynctask实现源码分析
- Android5.0 Lollipop DisplaySettings分析
- Android5.0双卡分析
- android5.0蓝牙框架分析
- Android5.0系统耗电分析
- android5.0 renderthread对应用层影响的分析
- Android5.0 源码分析--- Launcher启动应用的过程
- android的AsyncTask分析
- AsyncTask的参数分析
- Android AsyncTask 分析内部实现
- AsyncTask异步加载的源码分析与实现实例
- AsyncTask源码分析及实现网络图片的下载
- android5.0的drawerLayout,toolBar,FloatingActionButton,NavigationView的实现
- Android5.0的ApiDemo
- Android5.0 ripple效果低版本的实现
- HTML DOM Event 对象
- plsql 远程访问Oracle报错
- Objective-C之谓词NSPredicate
- iOS 保持界面流畅的技巧(转)
- ios同一个Label中的字符设置不同的字体
- Android5.0 AsyncTask的实现分析
- Volley源码分析 (三):如何分发结果
- 几何公式总结
- 2015-12-09复习之CSS(3)基础
- 第8章总结
- PHP require和include 路径问题
- 优米的最新手机配置Umi Rome 4G
- [javase学习笔记]-1.2 Java语言概述
- 分治策略(2)