Как управлять Loopers и Threads (поток больше не умирает!) - PullRequest
9 голосов
/ 08 июня 2011

Я создал класс, расширяющий поток, чтобы получать местоположение пользователя через LocationManager в потоке, не являющемся пользовательским интерфейсом.Я реализовал это как поток, потому что он должен запускаться по запросу и выполнять свою работу только в течение ограниченного времени.Кстати, мне пришлось добавить объект Looper в поток, чтобы иметь возможность создать обработчик для LocationManager (onLocationChanged).

Это код:

public class UserLocationThread extends Thread implements LocationListener {
//...
public void run() {
    try {
        Looper.prepare();
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
        Looper.loop();
        Looper.myLooper().quit();
    } catch (Exception e) {
        //...
    }
}

@Override
public void onLocationChanged(Location location) {
    locationManager.removeUpdates(this);
    //...
    handler.sendMessage(msg); //this is the handler for communication with father thread
}

//...}

Я бы хотел, чтобы поток запускался, получал данные о местоположении пользователя (в данном случае только один раз), отправлял данные в основной поток черезсообщение для обработчика, а затем умереть.Проблема в том, что в моем случае поток больше не умирает после завершения метода run (это должно быть хорошо, потому что в противном случае onLocationChanged не будет получать новые местоположения).

Но в этом случае, предполагая, что потокметоды stop и suspend устарели, какой будет хороший способ, по крайней мере, в этом случае, сделать поток с кубиком с петлителем?

Заранее спасибо;)

Ответы [ 5 ]

20 голосов
/ 08 июня 2011

Вы можете явно выйти из цикла Looper, используя Handler:

private Handler mUserLocationHandler = null;
private Handler handler = null;

public class UserLocationThread extends Thread implements LocationListener {    

 public void run() {
    try {
          Looper.prepare();
        mUserLocationHandler = new Handler();
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
        Looper.loop();

    } catch (Exception e) {
        //...
    }
}


@Override
public void onLocationChanged(Location location) {
    locationManager.removeUpdates(this);
    //...
    handler.sendMessage(msg); 
    if(mUserLocationHandler != null){
        mUserLocationHandler.getLooper().quit();
    }
}
0 голосов
/ 30 января 2017

Looper().quit(); хорошо, и в соответствии со спецификацией:

Заставляет метод loop () завершаться без обработки каких-либо сообщений в очереди сообщений.

Но если у вас есть задача, которая уже обрабатывается, и вы хотите остановить ее, вы можете получить рабочий поток и вызвать его прерывание:

@Override
public void onLocationChanged(Location location) {
    locationManager.removeUpdates(this);
    handler.sendMessage(msg); //this is the handler for communication with father thread
    if(mUserLocationHandler != null){
        mUserLocationHandler.getLooper().quit();
        mUserLocationHandler.getLooper().getThread().interrupt(); // <-- here
    }

}

Это работаетнормально с большинством операций ввода-вывода и блокировкой / ожиданием потока.

0 голосов
/ 14 ноября 2014

IntentService хорош для выполнения этой работы.

IntentService - это базовый класс для служб, которые обрабатывают асинхронные запросы (выраженные в виде содержимого) по требованию. Клиенты отправляют запросы через вызовы startService (Intent); служба запускается по мере необходимости, обрабатывает каждое намерение по очереди, используя рабочий поток, и останавливается, когда заканчивается его работа.

0 голосов
/ 19 сентября 2014

"Я реализовал это как протектор, потому что он должен запускаться по запросу и выполнять свою работу только в течение ограниченного времени."

Звучит как идеальная причина для простого повторного использования основного петлителя. Нет необходимости создавать новую тему здесь. Если вы выполняете работу по блокировке (сетевой ввод-вывод и т. Д.) В onLocationChanged (), в этот момент вы можете запустить ASyncTask.

Реализуйте LocationListener в вашей Activity / Service или любом другом и позвольте ему использовать основной петлитель по умолчанию.

Создание нового потока, установка его в цикл, а затем немедленное завершение не требуется.

0 голосов
/ 08 июня 2011

Расширение класса AsyncTask . Он автоматически выполняет все операции с потоками и обрабатывает их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...