【问题标题】:Quit the Looper of a Thread退出线程的 Looper
【发布时间】:2018-08-12 01:35:58
【问题描述】:

这是一个关于如何处理Android中的线程和循环器的更一般的问题,因此代码有点笼统。

考虑以下类DoSomethingClass,它必须启动某种需要侦听事件的动作(如蜂窝 rssi 变化、位置变化等)。

public class DoSomethingClass {
    private Thread listenForSomethingThread;

    private void startDoingSomething() {
        listenForSomethingThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                SomethingListener listener = new SomethingListener() {
                    @Override
                    public void onSomethingHappened(Something something) {
                        // Quit looper if interrupted
                        if (Thread.currentThread().isInterrupted()) {
                            Looper.myLooper().quit();
                        } else {
                            // Do stuff with the Something if not                           
                        }
                    }
                }

                SomethingManager somMan = // Retrieve it
                somMan.requestSomethingUpdates(listener);
                Looper.loop();  // Blocks until Looper is quitted
                somMan.removeSomethingUpdates(listener);                
            }
        });
        listenForSomethingThread.start();
    }

    private void stopDoingSomething() {
        listenForSomethingThread.interrupt();
    }
}

非常简单:当我调用startDoingSomething() 时,会生成一个新线程,它会创建一个侦听器来侦听事件并处理它们(例如,日志记录、自动对呼叫者大喊大叫等)。为此,它准备并启动一个 Looper。

当我完成时,我调用stopDoingSomething(),它会中断线程:在下一个事件中,什么都不会做,但是线程会清理并终止。

问题来了:如果那个事件从不发生怎么办?那么就永远不会调用中断检查,looper永远不会退出,永远循环!?

有什么方法可以从另一个线程中获取一个线程的 Looper,以便退出它?或者有没有可能让它除了正常的听者之外还听时间间隔?

【问题讨论】:

  • developer.android.com/reference/android/os/Looper :在这个例子中你会看到你可以通过发送消息与looper进行交互。现在,如果您想退出发送该消息。如果您使用带有消息示例的 google android looper,将会出现许多示例
  • 我建议您使用HandlerThread 并实现与之关联的Handler。您可以将消息传递给处理程序,并且您可以定义一个特殊的用于退出线程
  • @nandsito:只使用HandlerThread 而不是Thread 对我来说是完美的,因为HandlerThread 有一个quit() 方法。不幸的是,从另一个线程调用它会无限期地阻塞应用程序。在我的示例中如何实现Handler

标签: android multithreading android-looper


【解决方案1】:

我稍微更改了您的代码示例。你可以像这样退出looper:

public class DoSomethingClass {
    private Thread listenForSomethingThread;
    private Looper looper; // create this field

    private void startDoingSomething() {
        listenForSomethingThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                looper = Looper.myLooper(); // store the looper here
                SomethingListener listener = new SomethingListener() {
                    @Override
                    public void onSomethingHappened(Something something) {
                        // Quit looper if interrupted
                        if (Thread.currentThread().isInterrupted()) {
                            Looper.myLooper().quit();
                        } else {
                            // Do stuff with the Something if not                           
                        }
                    }
                }

                SomethingManager somMan = // Retrieve it
                somMan.requestSomethingUpdates(listener);
                Looper.loop();  // Blocks until Looper is quitted
                somMan.removeSomethingUpdates(listener);                
            }
        });
        listenForSomethingThread.start();
    }

    private void stopDoingSomething() {
        looper.quit(); // quit the looper
        listenForSomethingThread.interrupt();
    }
}

但是我猜这个 Looper 没有做任何事情,因为它的消息队列没有收到任何消息。侦听器可能在 UI 线程中运行,我想这不是您想要的。

【讨论】:

  • 所以你基本上是从外面直接将电缆铺设到弯针上。那么在looper.quit()之前打断不是更好吗?
  • @Bowi 中断只是给线程的信号。通过中断线程并退出 Looper,您正在混合使用两个 Android 线程 API,这会增加复杂性并可能导致混淆。此外,正如我在答案中所说,弯针线程没有做任何工作。我想您在尝试编写 Android Looper 之前需要有关设计的建议
猜你喜欢
  • 2011-02-17
  • 2013-07-11
  • 2013-07-30
  • 2018-05-20
  • 2013-09-17
  • 1970-01-01
  • 2012-01-16
  • 2012-04-25
  • 1970-01-01
相关资源
最近更新 更多