1

これは、スレッドについて私をいつも少し混乱させてきたものです。

LocationManager を使用して Android デバイスの現在の場所を見つけるスレッドがあります。次に、UI を更新してその場所を表示します。

実際、場所を取得するために LocationFinder というクラス全体を作成しました。そう言えば

String yourLocation = (new LocationFinder).getLocation();

ただし、LocationFinder の getLocation() メソッドは別のスレッドで実行されます。だから一概には言えない

String yourLocation = (new LocationFinder).getLocation();

場所を見つけるのに数分の一秒かかるため、返される即時値は確かに場所ではないためです。内部メソッドが戻り値を実際の位置に設定するまで、getLocation() はデフォルトで「notset」を返します。

とにかく、私はこれにアプローチする方法に困惑しています。アプリが数ミリ秒間ロックされるのは非常に煩わしいので、場所が見つかるまでブロックしたくありません。AsyncTask は、getLocation() を呼び出すときに既に使用されているため、使用したくありません。AsyncTaskをネストするのは間違いだと思います。

この階層の疑似コードは次のとおりです。

public class MainActivity extends Activity {

    Button locationButton = new Button(locationButtonClickListener);
    LocationFinder locationFinder = new LocationFinder();

    OnClickListener   locationButtonClickListener = new OnClickListener() {

        locationButton.setText(locationFinder.getLocation());
    }

}

public class LocationFinder {

    String city = "notYetSet";

    public String getLastLocation() {
         (new LastKnownLocationFinder).execute();
         return city;
    }

    public String getGPSLocation() {
         (new GPSLocationFinder).execute();
         return city;
    }

    private class LastKnownLocationFinder extends AsyncTask {

          protected String doInBackground {
               city = [lots of code to get last known location];
          }
    }

    private class GPSLocationFinder extends AsyncTask {

          protected String doInBackground {
               city = [lots of code to get location using GPS];
          }
    }
}

うまくいけば、それは私が得ていることを示しています。

ありがとうございました。

4

3 に答える 3

1

LocationListener を使用できます。このようにして、新しい場所が利用可能になるとすぐにコードが実行され、スレッドをブロックする必要がなくなります。

詳細: http://developer.android.com/reference/android/location/LocationListener.html

于 2013-07-08T00:17:53.860 に答える
1

アプリケーションが最後に使用した都市の場所をプリファレンスに保存します。

アプリケーションが起動/再起動するたびに (または、より正確には、アプリケーションが UI スレッドを再開するたびに)、独自のバックグラウンド スレッドで getLastLocation() を実行し、結果の都市を上で説明した設定に保存します。この方法はアンテナに電力を供給せず、バッテリーを消耗しないので、それほど頻繁に実行しても問題ありません。

そして、タイトルの元の質問への答えとして、いいえ、「スレッドを待機しても、スレッドを使用する目的が損なわれることはありません」。そのコンテキストでの「待機」という用語は、混乱を招く可能性があります。結果が表示されるのを「待機」し、その間に完全に機能する UI をレンダリングすることは、UI スレッドが結果を「待機」してから単一のピクセルを描画し、その結果が得られるまで UI からすべてをフリーズすることとは異なります。その意味では、2 つの異なる非同期バックグラウンド スレッドを使用しているかどうかは、それらが最初の UI スレッドからフォークされている (ネストされていない) 限り、問題ではありません。

そして、onclicklistener に配置する唯一のコードは、進行状況の回転ホイールを表示し、バックグラウンドで getgpslocation を実行して値を設定に挿入し、コンテンツの更新をトリガーする非同期タスクです。

于 2013-07-08T00:19:38.953 に答える
1

スレッドは作業を分割するためにあり、ほとんどの場合、並列 (非同期) で実行されます。それ以外の理由はほとんどありません。場合によっては、2 番目のスレッドが結果を処理する (同期) ために、1 つのスレッドが何かを完了する必要があります。

ここで、100% の時間で両方のスレッドの作業がシーケンシャルであることがわかっている場合、理論的には、2 つのスレッドを持つ必要はありません。場合によっては、さまざまな作業をさまざまなコンポーネントにカプセル化したい場合を除きます。

Android に関して言えば、アプリケーションはすべての UI 要素の変更を制御するための 1 つのスレッド (UI スレッド / メインスレッド) で開始され、ブロックされたり、スリープ状態になったり、長時間の操作が有効になったりすることはありません。これは、ユーザーが経験する遅延や無反応を減らすことです (これは、現在行っているようです)。

あなたの場合、すべてが正しく行われているようですがgetLocation()、AsyncTask が完全に実行されて値を変更するのに十分な時間がないため、呼び出されたときに常に "notset" が返されます。 .

interfaceの間で通信し、見つかった位置信号を送信する を構築する必要があります。場合によっては、位置をすぐに送信することもできます。LocationFinderMainActivity

public class LocationFinder {

    private CommunicateLocationFinder mCommunicate;

    public interface CommunicateLocationFinder {
        void LocationFinderSendGpsLocation(String location);
    }

    public LocationFinder (Activity activity){
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCommunicate = (CommunicateLocationFinder) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement CommunicateLocationFinder");
        }
    }

    private class GpsLocationFinder extends AsyncTask {
        protected String doInBackground {
            /*
             * Your work here
             */
        }

        protected void onPostExecute (String result){
            mCommunicate.LocationFinderSendGpsLocation(result);
        }
    }

    /*
     * Rest of your code
     */
}

public class MainActivity extends Activity implements 
        LocationFinder.CommunicateLocationFinder {

    @Override
    public void LocationFinderSendGpsLocation(String location){
        locationButton.setText(location);
    }

    /*
     * Rest of your code
     */

}

それが役に立てば幸いです、お知らせください、乾杯。

于 2013-07-08T00:22:31.053 に答える