9

Threadを拡張するクラスを作成して、UI以外のスレッドでLocationManagerを介してユーザーの場所を取得しました。リクエストに応じて開始し、限られた時間だけ作業を行う必要があるため、これをスレッドとして実装しました。ちなみに、LocationManager(onLocationChanged)のハンドラーを作成できるようにするには、スレッドにLooperオブジェクトを追加する必要がありました。

これはコードです:

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メソッドが非推奨になったとすると、少なくともこの場合、ルーパーダイを使用してスレッドを作成するための良い方法は何でしょうか。

前もって感謝します ;)

4

5 に答える 5

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();
    }
}
于 2011-06-08T11:59:18.607 に答える
0

「これは、要求に応じて開始し、限られた時間だけ作業を行う必要があるため、トレッドとして実装しました。」

これは、単にメインルーパーを再利用する完璧な理由のように思えます。ここで新しいスレッドを生成する必要はありません。onLocationChanged()でブロッキング作業(ネットワークI / Oなど)を実行している場合は、その時点でASyncTaskを起動できます。

アクティビティ/サービスなどにLocationListenerを実装し、デフォルトでメインルーパーを使用できるようにします。

新しいスレッドを生成し、ループするように設定してから、すぐに終了する必要はありません。

于 2014-09-18T21:03:36.620 に答える
0

IntentServiceは、この作業を行うのに適しています。

IntentServiceは、非同期要求(Intentsとして表される)をオンデマンドで処理するサービスの基本クラスです。クライアントはstartService(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 に答える