【问题标题】:Working around Android SDK bug: Handler.getLooper() clears thread interruption status解决 Android SDK 错误:Handler.getLooper() 清除线程中断状态
【发布时间】:2020-06-30 20:48:23
【问题描述】:

我花了几个小时追查我的代码丢失线程中断状态的原因,结果发现它实际上是由 Android SDK 中的错误引起的!看看Looper.getLooper()方法:

    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason isAlive() returns false, this method will return null. If this thread
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

请注意,它会吃InterruptedException 而不会重新中断!

既然我知道我的代码没有问题,那么解决这个问题的最佳方法是什么?我是否应该在调用.getLooper() 之前将线程的中断状态存储到一个标志中,然后在调用之后,如果设置了标志,我应该中断自己吗?任何想法将不胜感激:)

【问题讨论】:

    标签: java android interrupt


    【解决方案1】:

    方法是公开的 您可以通过从这个扩展来创建自己的处理程序,并覆盖该方法以使其执行您想要的操作,而无需调用超级

     public class BetterHandler extends Handler {
       @Override
       public Looper getLooper(){ 
            if (!isAlive()) {
            return null;
        }
    
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                   throw e
                }
            }
        }
        return mLooper;
       }
    
     }
    

    并在您需要的任何地方使用新的处理程序。 显然,你不能为那些在你的代码之外使用它的人替换处理程序类。

    【讨论】:

    • Facepalm 哦,呵呵!为什么我没有想到呢?我很快就会试试这个:)
    • 好吧,我试过了,首先,问题出在HandlerThread,而不是Handler。但除此之外,由于某种原因,当我试图重写该方法时,编译器声称它无法访问mLooper(也无法访问超类中的任何其他变量)。所以我最终做的是完全复制这个类(毕竟它只是Thread 的一个薄包装)并在我的副本中编辑方法。我可能会向 AOSP 提交 PR 来解决这个问题 :)
    猜你喜欢
    • 2013-01-11
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    相关资源
    最近更新 更多