Android - AsyncTask & HandlerThread
一、AsyncTask : 使用其在后台线程上运行代码
1、泛型参数说明:1)输入参数类型; 2)发送给进度更新所需类型; 3)doInBackground() 参数类型
2、主要回调函数:
a、doInBackground() 在后台线程运行代码
b、onPostExecute() 线程执行完回调该函数
c、onProgressUpdate() 执行UI更新;doInBackground中调用publishProgress后将回调该函数
3、开启与终止
a、execute() 开启后台线程执行;
b、cancel(true) 直接终止doInBackground所在线程;
cancel(false) 设置isCancelled()状态为true,doInBackground中检查isCancelled()状态可以温和终止线程;
4、Android 3.2版本起,AsyncTask不再为每一个AsyncTask实例单独创建一个线程。
相反,它使用一个Executor在单一的后台线程上运行所有AsyncTask的后台任务。
这意味着每个AsyncTask都需要排队逐个执行,显然,长时间运行的AsyncTask会阻塞其他AsyncTask。
二、异步消息处理机制
0、Android中,控件没有实现成为线程安全类型;
1、Android系统中,使用消息队列(message queue)的线程叫做消息循环(message loop)。消息循环会不断循环检查队列上是否有新消息,消息循环由一个线程和一个Looper组成,Looper对象管理着线程的消息队列。
2、主线程也是一个消息循环,主线程所有工作都是由其Looper完成,Looper不断从消息队列中抓取消息,指派给消息目标处理;
为线程创建Looper的方法如下:在线程run()方法当中先调用Looper.prepare()初始化Looper,然后再run()方法最后调用Looper.loop(),这样我们就在该线程当中创建好Looper。(注意:Looper.loop()方法默认是死循环)
3、Message 消息,包含几个实例变量:
what 定义消息的int型代码
obj 随消息发送的用户指定对象
target 处理消息的Handler
4、Handler 不仅是Message的目标(target),也是创建和发布Message的接口;
一个handler仅与一个Looper关联,这样通过handler发布消息才能进入Looper拥有的消息队列中;
在线程中实例化Handler对象,需要保证线程当中包含Looper(注意,UI-thread默认包含Looper);
5、传递Handler:主线程上创建的Handler会自动与它的Looper相关联,可以将主线程上创建的handler传递给另一个线程,传递出去的handler与创建它的线程Loooper始终保持着联系;
因此,任何已创出handler负责处理的消息都将在主线程的消息队列中处理。
三、可以使用HandlerThread类创建一个消息循环后台线程 ,HandlerThread 使用步骤:
1、创建一个HandlerThread
,即创建了一个包含Looper的线程。
HandlerThread handlerThread = new HandlerThread("leochin.com");
handlerThread.start(); //创建HandlerThread后一定要记得start()
2、获取HandlerThread
的Looper
Looper looper = handlerThread.getLooper();
3、创建Handler,通过Looper初始化
Handler handler = new Handler(looper); //handler与looper关联
4、终止HandlerThread,handlerThread.quit();
5、一个完整示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | public class ThumbnailDownloader<Token> extends HandlerThread { private static final String TAG= "ThumbnailDownloader" ; private static final int MESSAGE_DOWNLOAD= 0 ; private Handler mHandler; private Handler mResponseHandler; //UI线程传入的Handler对象 private Listener<Token> mListener; private Map<Token,String> requestMap=Collections.synchronizedMap( new HashMap<Token,String>()); public interface Listener<Token>{ void onThumbnailDownloaded(Token token,Bitmap thumbnail); } public void setListener(Listener<Token> listener){ mListener=listener; } public ThumbnailDownloader(Handler responseHandler){ super (TAG); mResponseHandler=responseHandler; } @Override protected void onLooperPrepared() { super .onLooperPrepared(); mHandler= new Handler(){ public void handleMessage(android.os.Message msg) { if (msg.what==MESSAGE_DOWNLOAD){ final Token token=(Token)msg.obj; try { final String url=requestMap.get(token); if (url== null ) return ; byte [] bitmapBytes= new FlickrFetcher().getUrlBytes(url); final Bitmap bitmap=BitmapFactory.decodeByteArray(bitmapBytes, 0 , bitmapBytes.length); mResponseHandler.post( new Runnable() { @Override public void run() { // if (requestMap.get(token)!=url){ return ; } requestMap.remove(token); mListener.onThumbnailDownloaded(token, bitmap); } }); } catch (IOException ioe){ Log.e(TAG, "Error downloading image" ,ioe); } } }; }; } public void queueThumbnail(Token token,String url){ Log.i(TAG, "Got an URL:" +url); requestMap.put(token, url); mHandler.obtainMessage(MESSAGE_DOWNLOAD, token).sendToTarget(); } public void clearQueue(){ mHandler.removeMessages(MESSAGE_DOWNLOAD); requestMap.clear(); } } |
好文链接:http://www.cnblogs.com/hnrainll/p/3597246.html
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· 卧槽!C 语言宏定义原来可以玩出这些花样?高手必看!
· langchain0.3教程:从0到1打造一个智能聊天机器人