如何管理Loopers和Threads(线程不再死了!)

时间:2011-06-08 11:22:13

标签: android multithreading handler looper

我创建了一个扩展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将不会收到新位置)。

但是通过这种方式,假设线程的stop和suspend方法已被弃用,那么至少在这种情况下,使用looper die创建一个线程会是一个好方法吗?

提前致谢;)

5 个答案:

答案 0 :(得分:20)

您可以使用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();
    }
}

答案 1 :(得分:0)

“我将其作为一个步骤来实现,因为它必须根据要求启动并在有限的时间内完成其工作。”

这听起来像是简单地重复使用主弯针的完美理由。这里不需要生成新的Thread。如果您正在onLocationChanged()中进行阻塞工作(网络I / O等),那么您可以启动ASyncTask。

在您的Activity / Service上实现LocationListener,默认情况下让它使用主循环器。

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

答案 2 :(得分:0)

IntentService很适合做这项工作。

  

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

答案 3 :(得分: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和线程锁定/等待。

答案 4 :(得分:-1)

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