AsyncTask中线程转换的实现
来源:互联网 发布:淘宝明星店铺收费 编辑:程序博客网 时间:2024/05/16 00:48
说明:最开始接触网络的时候,那时候尝试写了写回调,但自己写不出线程的转换来,就必须在回调方法中写上runOnUiThread方法来切换到主线程。最近研究了一下Android中的线程,一时冲动有了写博客的想法,来记录下自己的成长之路。
Android中一般采用Handler来实现主线程与子线程的切换,这是最常用的,就不再废话了,那么我们来看一下AsyncTask的实现。
AsyncTask的使用前提是,必须在主线程中创建AsyncTask的子类对象,那么这个前提正是可以获取主线程的基础。
private static InternalHandler sHandler;
这是AsyncTask里的一个静态成员变量,显然,它就是线程转换的关键类,下面是InternalHandler的源码
private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } } }
可以看到InternalHandler的构造方法中调用了Handler的Handler(Looper looper)这个构造方法,将主线程的looper传入,那么这个handler处理消息就会在looper的线程中执行。
继续来看Handler的源码
public Handler(Callback callback, boolean async) { ...... mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
这里也证明了如果在一个线程中没有执行Looper.prepare()方法,直接创建Handler是会抛出异常的,mLooper = Looper.myLooper(); 打开Looper的myLooper方法,来看源码
public static @Nullable Looper myLooper() { return sThreadLocal.get(); }
可以看到Looper用一个ThreadLocal
Thread currentThread = Thread.currentThread();
其它代码不再贴出,但是到此我们可以看出Looper与创建Looper的线程是相联系的,我们使用Looper来从MessageQueue并交给Handler的HandleMessage来处理
回到主题
在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); } };
可以看到在doPackground方法执行完成后会调用postResult方法并将结果传入,来看postResult方法
private Result postResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
getHandler的实现
private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; } }
可以发现最终会有InternalHandler来执行发送消息的方法,因为InternalHandler肯定是主线程的Handler,那么最终处理消息肯定是在主线程中
来看InternalHandler的handleMessage方法的源码
public void handleMessage(Message msg) { AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; } }
由语义就可以看出一个是得到了结果,一个是更新进度
更新进度会调用onProgressUpdate方法,得到结果会调用result.mTask.finish(result.mData[0]);
下面是mTask.finish()方法的源码
private void finish(Result result) { if (isCancelled()) { onCancelled(result); } else { onPostExecute(result); } mStatus = Status.FINISHED; }
可以看到如果任务被取消会调用onCancelled方法,否则执行onPostExecute方法
总结:AsyncTask之所以可以在主线程执行进度更新的方法和onPostExecute方法,关键的类就行内部维护了一个肯定在主线程的类InternalHandler,本质就是Handler,由这个类来执行onProgressUpdate与onPostExecute方法,那么就实现了线程的转换。
- AsyncTask中线程转换的实现
- AsyncTask机制实现线程之间的通信
- AsyncTask中关于线程的问题
- AsyncTask 的线程池
- android AsyncTask的方法在哪几个线程中调用
- Android AsyncTask中后台线程堵塞的原因分析
- 【Android】在不同的线程池中执行AsyncTask
- 线程的改进--------AsyncTask 介绍
- AsyncTask的线程池使用
- AsyncTask与线程的区别
- AsyncTask的实现原理
- AsyncTask实现的原理
- AsyncTask的实现原理
- AsyncTask的实现机制
- AsyncTask的实现
- AsyncTask的实现原理
- AsyncTask Android的线程和线程池
- Android开发中AsyncTask实现异步处理任务的方法
- 视频(一到十四):uboot编译,dnw,环境配置等
- TabBar的颜色处理方案
- 用WinHex解析分区表
- The7 — 响应式多用途 WordPress 主题 免费下载
- adb相关资源
- AsyncTask中线程转换的实现
- ubuntu软件中心安装matlab快捷方式总是卡死的解决方法
- 使用VB.NET遇到的若干问题及解决方案
- js对象,Event对象
- 大数据
- Servlet小总结
- ACdream 1017 Fast Transportation (网络流+分层图)
- [BZOJ1616][Usaco2008 Mar]Cow Travelling游荡的奶牛(dfs||dp)
- 日期类 Date SimpleDateFormat Calendar