android在非UI线程中更新UI

来源:互联网 发布:手机淘宝页头图片 编辑:程序博客网 时间:2024/05/23 01:40

Android采用UI单线程模型,如果在非UI线程直接对UI进行了操作,则会报错:

CalledFromWrongThreadException:only the original thread that created a view hierarchy can touch its views

所以不能直接在非ui线程操作ui,那如果有这个需求怎么办呢,有以下几种方法

概述

  1. handler
  2. View的post方法,本质上就是添加到主线程的消息队列里
  3. runOnUiThread(Runnable),这是Activity的一个方法,在Activity类里建线程就可以用,缺点是需要一个Activity引用
  4. 使用AsyncTask
  5. asyncTask和handler是最常用的,asyncTask内部是有handler的相当于对handler做了封装。asyncTask内部实际只有一个线程(默认实现方法,当然你可以提供Executor解决此问题)。如果你的任务很耗时,那后面的任务无法执行。asyncTask不适合长期任务


view的post方法

    public boolean post(Runnable action) {        final AttachInfo attachInfo = mAttachInfo;        if (attachInfo != null) {            return attachInfo.mHandler.post(action);        }        // Assume that post will succeed later        ViewRootImpl.getRunQueue().post(action);        return true;    }
看源码可以发现post就是把当前runnable加到消息队列里去,2种方法ViewRootImpl.getRunQueue().post(action)或者attachInfo.mHandler.post(action)

Activity的runOnUiThread

本质也是调用handler的post方法
/**     * Runs the specified action on the UI thread. If the current thread is the UI     * thread, then the action is executed immediately. If the current thread is     * not the UI thread, the action is posted to the event queue of the UI thread.     *     * @param action the action to run on the UI thread     */    public final void runOnUiThread(Runnable action) {        if (Thread.currentThread() != mUiThread) {            mHandler.post(action);        } else {            action.run();        }    }

判断当前线程是否是主线程

判断当前线程是否是主线程主要2种方法

Looper.myLooper() == Looper.getMainLooper()
以及
Thread.currentThread() == Looper.getMainLooper().getThread() 

有些场景会用到如下代码
public final void runOnUiThread(Runnable action) {        if (Thread.currentThread() != mUiThread) {            mHandler.post(action);        } else {            action.run();        }    }



总结

handler和asyncTask是用的比较多的。AsyncTask面对handler的不足之处AsyncTask虽然是个轻量级的类(实际线程由ExecutorService管理),但不适合频繁操作,因为这很快会聚集需要垃圾回收的对象,导致界面卡顿。而且不能设置执行时间,也无法间隔一段时间执行操作。

补充

对话框操作也属于ui操作,必须主线程

参考资料

http://blog.csdn.net/mylzc/article/details/6736988
http://blog.csdn.net/guolin_blog/article/details/11711405(好文章)
http://www.cnblogs.com/xiaoluo501395377/p/3430542.html
http://blog.csdn.net/honeybaby201314/article/details/42680607
0 0