Android开发之子线程操作UI的几种方法
在android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新ui,下面就自己经历的一些项目总结一下更新的方法:
在看方法之前需要了解一下android中的消息机制。
方法1 activity.runonuithread
方法如下:
runonuithread(new runnable() { @override public void run() { tv.settext("hello"); } });
这种方法简单易用,如果当前线程是ui线程,那么行动是立即执行。如果当前线程不是ui线程,就发布到事件队列的ui线程。其实和handler差不多,都是将这个更新ui的请求消息,加入到事件队列,等待主线程空闲的时候执行。
方法2 handler
主线程中定义handler如下:
handler mhandler = new handler() { @override public void handlemessage(message msg) { super.handlemessage(msg); switch (msg.what) { case 0: string data = (string)msg.obj; textview.settext(data); break; default: break; } } };
子线程发消息,通知handler完成ui更新,代码如下:
new thread(new runnable(){ @override public void run() { //耗时操作 mhandler.sendemptymessage(0); message msg =new message(); msg.obj = "数据";//可以是基本类型,可以是对象,可以是list、map等 mhandler.sendmessage(msg); } }).start();
方法3 view.post
final button btn =(button)findviewbyid(r.id.btn); btn.post(new runnable(){ @override publicvoid run() { btn.settext("hello"); } });
上面的代码就是更新btn中的内容,同样下面的代码也可以达到这种效果。
handler handler = new handler(); final button btn = (button)findviewbyid(r.id.btn); handler.post(new runnable(){ @override public void run() { btn.settext("hello"); } });
这个是用handler.post方法,一个是用view.post方法,handler.post方法已经在android的消息机制中介绍过了,其实最终也是调用了方法2中的send方法。
现在看一下view.post方法的源代码:
public boolean post(runnable action) { handler handler; attachinfo attachinfo = mattachinfo; if (attachinfo != null) { handler = attachinfo.mhandler; } else { // assume that post will succeed later viewrootimpl.getrunqueue().post(action); return true; } return handler.post(action); }
方法中主要的功能代码就是attachinfo.mhandler,获取当前线程(即ui线程)的hanlder,然后将action对象post到handler里。在handler里的处理过程上面链接文已经分析的很清楚了,它将传递过来的action对象包装成一个message(message的callback为action),然后将其投入ui线程的消息循环中。在handler的dispatchmessage方法里,第一句话就是为它所设,直接调用runnable的run方法。而此时,已经路由到ui线程里,因此,我们可以毫无顾虑的来更新ui。
方法4 广播
子线程中发送广播,主线程中接收广播并更新ui。
方法5 使用asynctask
为了简化子线程中访问ui,系统提供给了我们asynctask。
asynctask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行进度和结果传递给主线程并更新ui。本质上来说asynctask封装了thread和handler,但是asynctask不适合进行特别耗时的后台任务,如果需要进行特别耗时的任务,建议使用线程池。
不同api版本的asynctask具有不同的表现,因此需要注意。为了控制篇幅,具体的asynctask的使用方法和工作原理,我打算后面单独成文进行介绍。
以上所述是小编给大家介绍的android开发之子线程操作ui的几种方法,希望对大家有所帮助