如何等待 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() 回调意图完成?的主要内容,如果未能解决你的问题,请参考以下文章

主程序如何通过等待而不是加入同时等待多个线程?

如何让异步/等待等待我的嵌套数组填充

如何使用 QProcess 等待子进程?

颤振:如何使用“等待”等待其他 BLoC 事件完成

如何等待发货?

调用condition_variable等待函数时线程如何等待?