Выйти из петли потока

Это более общий вопрос о том, как обрабатывать потоки и петли в Android, поэтому код немного обобщен.

Рассмотрим следующий класс DoSomethingClass, который должен запустить какое-то действие, которое требует прослушивания событий (например, изменения сотовой сети, изменения местоположения и т. д.).

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()создается новый поток, который создает слушателя, который прослушивает события и обрабатывает их (например, ведение журнала, автоматический крик на вызывающих и т. д.). Для этого он готовит и запускает петлитель.

Когда я закончу, я звоню stopDoingSomething(), который прерывает поток: при следующем событии ничего не будет сделано, но поток очистится и прекратит работу.

И вот проблема: что, если это событие никогда не произойдет? Тогда проверка на прерывание никогда не будет вызвана, петлитель никогда не будет завершен и будет работать вечно!?

Есть ли способ получить Looper потока из другого потока, чтобы выйти из него? Или есть возможность позволить ему слушать интервалы времени в дополнение к своим обычным слушателям?

1 ответ

Я немного изменил пример кода. Вы можете выйти из петлителя следующим образом:

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();
    }
}

Но я думаю, что этот петлитель ничего не делает, потому что его очередь сообщений не получает никаких сообщений. Слушатель может работать в потоке пользовательского интерфейса, что, я полагаю, не то, что вы хотите.

Другие вопросы по тегам