Android 异步任务:AsyncTask深入探讨
来源:互联网 发布:英雄无敌3 数据修改 编辑:程序博客网 时间:2024/06/05 04:48
围绕 Thread和Handler基础实现的UI帮助类。可以在非UI线程中处理事务并将结果给UI主线程。
1 最多几秒钟的操作,如果需要保持后台任务执行很长时间。强烈建议使用java.util.concurrent包提供的APIs. 比如Executor、ThreadPoolExecutor、FutureTask等
2 继承AsyncTask<Params,progress,Result>
在调用execute()时传入Params.
3 必须实现Result doInBackground(Params…p) 具体指的是execute()时传入可变参数Params。
返回值是继承AsyncTask<Params,progress,Result>
时的Result泛型实例化类型。
比如MyLoginAsyncTask extends AsyncTask<User user,Integer,Boolean>
传入的User参数,返回Boolean类型。
还要有接收任务处理的结果方法 onPostExecute(Result r);
4 可选实现 onPreExecute() 和 onProgressUpdate()
5 如果实现onProgressUpdate() 来更新UI进度显示View则要在doInBackground(Params…p)发布进度(publishProgress())
6 onPreExecute() 、onProgressUpdate()、onPostExecute(Result r);运行在Ui进程内。
7 执行顺序onPreExecute()[通常准备UI]-> doInBackground(Params…p)[可以调用publishProgress()->onProgressUpdate()]->onPostExecute(Result r) or onCanclled()
8 AsyncTask
只能在Ui线程中被创建 加载 和调用。开发者不能手动调用常用方法。
9*任务实例化后只能被执行一次 再次执行会抛出异常。
异步任务保证以下操作是线程安全的:
10 创建时设置外部参数或者在onPreExecute()引用这些参数
11 doInBackground(Params…p)设置参数和引用他们
荔枝:
public class UserRegisteTask extends AsyncTask<Void, Void, Integer> { private final User user; UserRegisteTask(String number, String password ,String name) { user = new User(); user.setNameid(number); user.setName(name); user.setPassword(password); } @Override protected Integer doInBackground(Void... params) { UserService mUserService = new UserService(eventHandler); return mUserService.register(user); } @Override protected void onPreExecute() { showProgress(true); } @Override protected void onPostExecute(final Integer code) { mRegisteTask = null; showProgress(false); if (code == ServicesResponseCode.REGIST_SUCCESS) { Toast.makeText(LoginActivity.this,"注册成功!",Toast.LENGTH_LONG).show(); } else if(code == ServicesResponseCode.USER_HAS_EXIST){ mPhoneNumberView.setError("用户已经存在"); mPhoneNumberView.requestFocus(); } } @Override protected void onCancelled() { mRegisteTask = null; showProgress(false); }}
深入剖析:
1 先来看Android 的一般UI中执行费时操作的办法
创建Runnable 执行体
创建Handler 并定义接受的消息体
执行Thread(Runnable) 在run方法发送消息
依赖于 Looper-Handler (message)
2 AsyncTask也要创建线程并向UI线程中依赖的Looper发送Message消息
和1的区别就是用了concurrent并发框架来做这件事
用了线程池来处理UI发出的多个Runnable
那么UI线程只要创建AsyncTask并将要执行的任务offer给并发框架就可以。
并发框架会分发线程任务。执行完每个任务后会向UI线程发送Message 结果
执行任务时也会发送Progress消息(得自己调用PublishProgress())
AsyncTask将Ui线程执行体包装成FutureTask(Callable)交给Executor
FutureTask在并发框架内执行完毕后会调用finishCompletion()
在该方法中会调用done()
我们在AsyncTask中创建FutureTask时覆写done()方法并调用get()方法就可以拿到执行结果。向UI线程发送Message 结果
3 再看一下代码实现
泛型参数多说两句:因为早晚类型擦出 只是编程时提前告诉该参数类型以保证类型安全和容器参数一致性
理解时候可以先从心里将AsyncTask<Void, Void, Integer>
做类型擦除。
用的时候想成提前做<T>
这种的类型限定。
3.1
定义为虚基类AsyncTask
告诉创建必须实现方法doInBackground(Params… params)
3.2
类类型:(不管创建多少AsyncTask实例 都共用的) BlockingQueue<Runnable>
线程池中多个线程共享的阻塞队列 ThreadPoolExecutor
线程池执行者 SerialExecutor
顺序执行者 还在UI进程中 向ThreadPoolExecutor offer(提供执行体);自身有一个容器ArrayDeque<Runnable>
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); } }}
值得一提的是 第二个scheduleNext()在UI进程中 有开启线池工作的作用
第一个在线程体中,起到持续执行ArrayDeque<Runnable>
容器中的FutrueTask的作用
看这段代码,感受到了浓浓的 生产者和消费者 模型呀!
不过这个代码将FutureTask又包装了一次。真正的FutureTask 是在阻塞队列里被等待执行的。
InternalHandler 也是类类型:用作向UI通知结果数据和过程进度数据
单重判断方法,锁加到了 类AsyncTask.class上
private static Handler getHandler() { synchronized (AsyncTask.class) { if (sHandler == null) { sHandler = new InternalHandler(); } return sHandler; }}
3.3
实例类型(每个实例不同)
创建AsyncTask时判断本实例运行状态相应的抛出 :
RUNNING throw IllegalStateException already running FINISHED throw new IllegalStateException executed only once
也就是说每个实例只能被执行一次。我们每次new了最好在最后将实例设为null。
mWorker:对具体业务的包装
mFuture:对mWorker做的可自动回调用结果处理办法的包装
4
弄个思路图瞅瞅
5**也有缺点**
每次任务都要弄个AsyncTask子类并覆写方法
如果一个Ui组件内有好几个任务 那得高好几个~
所以最好自己在封装一个框架 直接告诉任务名字和传入任务实体 11月18号更新
- Android 异步任务:AsyncTask深入探讨
- 深入学习Android异步任务-AsyncTask
- 深入理解异步任务AsyncTask
- Android异步任务AsyncTask
- Android--AsyncTask异步任务
- Android AsyncTask异步任务
- Android 异步任务 AsyncTask
- android 异步任务 AsyncTask
- Android AsyncTask 异步任务
- Android AsyncTask异步任务
- 【Android】异步任务AsyncTask
- Android AsyncTask异步任务
- android AsyncTask异步任务
- Android异步任务AsyncTask
- Android:AsyncTask -- 异步任务
- Android 异步任务:AsyncTask
- Android异步任务AsyncTask
- Android异步任务AsyncTask
- Docker学习总结
- Ubuntu14.04环境下配置TFTP服务器
- Git 服务器搭建与客户端安装
- Python的for…else和while…else语法
- codeforce 1C Ancient Berland Circus
- Android 异步任务:AsyncTask深入探讨
- HDU
- 深入剖析nginx平滑重启
- 存储过程入门
- Netty----什么是Netty学习
- spring mvc + shiro
- 第十五天 jquery和ajax
- Java-数字分类 (20)
- C++_013_数据结构_队列类