稍微有过Andorid开发经验的同学都知道,Android开发中涉及到UI变动的操作,必须在主线程中执行, 否则会crash, 报错如下:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

这就需要我们将代码抛到主线程执行。
第一种方式,是通过Activity.runOnUiThread()来做。这不是一个好方法,毕竟Activity这种东西,在子线程中可遇不可求。也千万不要因此而将Activity传来传去,甚至对Context进行强转,那样太过难看。
那么,只剩下通过Handler手动将代码抛到主线程了。这就需要,Handler具有主线程的Looper对象。具体的原因可以参考我之前的博客:【Android】结合源码解析Android消息队列工作流程 。
两种实现方式:
1. 在主线程中创建Handler
2. 直接通过MainLooper,构造handler

这里抛弃方法1, 因为那样会依赖到全局变量。我们采用方法2, 创建如下一个单例类:

public class MainHandler extends Handler {    private static volatile MainHandler instance;    public static MainHandler getInstance() {        if (null == instance) {            synchronized (MainHandler.class) {                if (null == instance) {                    instance = new MainHandler();                }            }        }        return instance;    }    private MainHandler() {        super(Looper.getMainLooper());    }}

在子线程中,使用:

MainHandler.getInstance().post(new Runnable() {    @Override    public void run() {        // your code    }});

这样就能随时随地,很方便地将代码抛到主线程中执行。

warning, 不要耍小聪明
在子线程执行UI操作会Crash, 根据报的错,

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

有些同学可能会想,在子线程创建一个looper不就ok了吗。于是他们会在子线程的开头,调用Looper.prepare,更机智的同学甚至会在子线程的末尾进行一下Looper.loop()。
嗯, 我们会发现,这样确实不会crash了(好棒)。然而,进行的UI操作,展现的效果,会跟我们的预想出现各种各样的偏差。

不信,你可以试试。

毕竟,Google的目的,是希望我们在单一的UI线程进行UI操作,通过是否创建了looper进行判断,只是一种手段。

更多相关文章

  1. Android(安卓)Okhttp主流程源码分析
  2. Android应用启动慢的问题
  3. Android(安卓)adb启动任意app的几种方式
  4. 消息处理机制 —Handler/Thread/Looper & MessageQueue
  5. android HandlerThread源码解析
  6. Android中的几种多线程实现
  7. Android(安卓)Toast 用法总结
  8. Android界面刷新
  9. 走进Java Android(安卓)的线程世界(三)Hander消息机制

随机推荐

  1. Android热补丁技术—dexposed原理简析(阿
  2. 我的Android进阶之旅------>Android中解
  3. Android.mk语法说明(android ndk开发)
  4. 【移动开发】Android无线调试 使用adbWir
  5. Android登录记住密码,AES加密保存密码
  6. Android 支付宝【支付】
  7. Android,似乎没那么友好.....
  8. Android——获取本机安装的应用程序
  9. 如何在Windows上设置Android环境变量/路
  10. 发送手机物理标识请求