【问题标题】:How to wait for requestLocationUpdates() callback intent to finish?如何等待 requestLocationUpdates() 回调意图完成?
【发布时间】:2018-02-28 23:36:49
【问题描述】:

我想等待FusedLocationProviderClient.requestLocationUpdates() 中的回调意图完成。带有超时的while循环是最好的解决方案吗?下面是一个示例,没有超时。

通常我会使用 startWakefulService() 来等待异步服务完成,但我不知道如何将它与 requestLocationUpdates() 一起使用。

Task t = flpc.requestLocationUpdates(locationRequest, pe);
while (! t.isSuccessful()) {
    Log.v(TAG, "Waiting for result...");
}

【问题讨论】:

    标签: java android asynchronous android-fusedlocation


    【解决方案1】:

    如果您对 RxJava/RxAndroid 有点熟悉,您可以将您的方法调用包装在 Observable 中(或 Callable、Single 等任何您认为最好的),然后在 UI 之外的另一个线程上运行它,然后一旦您拥有你方法的结果,你会在主线程上收到它,然后用它做任何你想做的事情。

    在代码中它看起来像这样:

    Observable.fromCallable(() -> flpc.requestLocationUpdates(locationRequest, pe))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(task -> onLocationUpdatesSuccess(task), throwable -> Log.e(TAG, throwable.getMessage()));
    

    否则另一种解决方案是将您的方法包装在 AsyncTask 中,例如,您最终会得到这样的结果:

        new AsyncTask<Void, Void, Task>() {
                @Override
                protected Task doInBackground(Void... params) {
                    return flpc.requestLocationUpdates(locationRequest, pe);
                }
    
                @Override
                protected void onPostExecute(Task task) {
                    onLocationUpdatesSuccess(task)
                }
        }.execute();
    

    【讨论】:

      【解决方案2】:

      这是我最终做的:

      使用手动唤醒锁。在你的类中声明一个静态唤醒锁变量。还要定义两个方法:acquire() 和 release()。

      acquire() 实例化一个唤醒锁并将其分配给您的类中的静态唤醒锁变量。它是一个实例方法(不是静态的),因为它使用需要上下文的 PowerManager。

      release() 是一个静态方法,因此其他类可以调用它。它释放唤醒锁。我使用带唤醒锁计数器的单例唤醒锁,在调用它时递减计数器,并在计数器为零时释放唤醒锁。但计数器是完全可选的。

      所有这一切的“诀窍”是创建一个实例唤醒锁并将其分配给一个静态变量。这允许在无法访问我的类实例的服务中修改唤醒锁。

      不是从类外部调用finish(),更简洁的解决方案是使用Task.OnCompleteListener() 来调用finish()。 requestLocationUpdates() 返回一个 Task 对象。

      【讨论】:

      • 我需要一个唤醒锁,但这在我最初的问题中并不清楚。所以我选择了另一个答案。
      【解决方案3】:

      这是我只获取 1 个位置的解决方案:

      private fun getNewLocation(): Single<Location> =
          Single.create { emitter ->
              locationClient.requestLocationUpdates(locationRequest, object : LocationCallback() {
                  override fun onLocationResult(result: LocationResult) {
                      locationClient.removeLocationUpdates(this)
      
                      val location = result.locations.firstOrNull()
                      if (location != null) {
                          emitter.onSuccess(location)
                      } else {
                          emitter.onError(NullPointerException("Null location"))
                      }
                  }
      
                  override fun onLocationAvailability(result: LocationAvailability) {
                      if (!result.isLocationAvailable) {
                          locationClient.removeLocationUpdates(this)
                          emitter.onError(IllegalStateException("Location not available"))
                      }
                  }
              }, Looper.getMainLooper())
          }
      

      locationRequest 的样子:

      private val locationRequest =
          LocationRequest()
              .setExpirationDuration(TimeUnit.SECONDS.toMillis(30L))
              .setInterval(TimeUnit.SECONDS.toMillis(15L))
              .setNumUpdates(1)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-09
        • 2016-02-17
        • 2021-11-13
        • 1970-01-01
        相关资源
        最近更新 更多