9

我创建了一个扩展 Thread 的类,以在非 UI 线程中通过 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 将不会接收新位置)。

但是以这种方式,假设线程的停止和挂起方法已被弃用,那么至少在这种情况下,使带有活套的线程死亡的好方法是什么?

提前致谢 ;)

4

5 回答 5

20

您可以使用以下命令显式退出Looper's 循环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();
    }
}
于 2011-06-08T11:59:18.607 回答
0

“我把它作为一个踏板来实现,因为它必须根据要求启动,并且只在有限的时间内完成它的工作。”

这听起来像是简单地重用主循环器的完美理由。无需在此处生成新线程。如果您在 onLocationChanged() 中进行阻塞工作(网络 I/O 等),此时您可以启动 ASyncTask。

在您的 Activity/Service 或其他任何东西上实现 LocationListener 并让它默认使用主循环器。

产生一个新线程,将其设置为循环,然后立即退出是不必要的。

于 2014-09-18T21:03:36.620 回答
0

IntentService 很适合做这项工作。

IntentService 是按需处理异步请求(表示为 Intent)的服务的基类。客户端通过 startService(Intent) 调用发送请求;该服务根据需要启动,使用工作线程依次处理每个 Intent,并在工作结束时自行停止。

于 2014-11-14T12:35:06.760 回答
0

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
    }

}

这适用于大多数 IO 和线程锁定/等待。

于 2017-01-30T18:45:01.580 回答
-1

扩展AsyncTask类。它会自动为您完成所有线程和处理。

于 2011-06-08T11:47:15.500 回答