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