如何等待 requestLocationUpdates() 回调意图完成?
Posted
技术标签:
【中文标题】如何等待 requestLocationUpdates() 回调意图完成?【英文标题】:How to wait for requestLocationUpdates() callback intent to finish? 【发布时间】: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...");
【问题讨论】:
【参考方案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)
【讨论】:
以上是关于如何等待 requestLocationUpdates() 回调意图完成?的主要内容,如果未能解决你的问题,请参考以下文章