首页 > 解决方案 > 如何使用使用回调的第三方库实现 CoroutineWorker?

问题描述

我正在尝试实现一个 CoroutineWorker 来在 Android 应用程序中做一些后台工作。我正在使用的第三方库使用 onConnected、onChanged 等回调。如何在 CoroutineWorker 中使用这个库?

这是我到目前为止所拥有的

override suspend fun doWork(): Result {
    return try {
        val appContext = applicationContext
        var mReporter: StepCountReporter?

        val mStepCountObserver = object : StepCountReporter.StepCountObserver {
            override fun onChanged(count: Int) {
                Log.d(APP_TAG, "Step reported : $count")
                // This is where the work is completed
            }
        }

        val mConnectionListener = object : HealthDataStore.ConnectionListener {

            override fun onConnected() {
                Log.d(APP_TAG, "Health data service is connected.")
                mReporter = StepCountReporter(mStore!!)
                if (isPermissionAcquired) {
                    mReporter!!.start(mStepCountObserver)
                } else {
                    Log.e(APP_TAG, "permissions not acquired")
                }
            }

            override fun onConnectionFailed(error: HealthConnectionErrorResult) {
                Log.d(APP_TAG, "Health data service is not available.")
            }

            override fun onDisconnected() {
                Log.d(APP_TAG, "Health data service is disconnected.")
            }
        }
        mStore = HealthDataStore(appContext, mConnectionListener)
        mStore!!.connectService()
        // wait for mStepCountObserver.onChanged to be called
    } catch (error: Throwable) {
        Result.failure()
    }
}

我正在尝试完成 mStepCountObserver.onChanged 中的协程,但看起来我应该Result.success在函数结束时调用。

标签: androidkotlinkotlin-coroutines

解决方案


您可以使用suspendCoroutine函数,它有助于将协程与 Callbacks 连接起来。

'suspendCoroutine' 暂停调用它的协程,并且仅在调用 'resume()' 或 'resumeWithException()' 时恢复该协程。


在你的情况下,

override suspend fun doWork(): Result {
        return try {
            val outputCount = suspendCoroutine<Int> {
                val appContext = applicationContext
                var mReporter: StepCountReporter?

                val mStepCountObserver = object : StepCountReporter.StepCountObserver {
                    override fun onChanged(count: Int) {
                        Log.d(APP_TAG, "Step reported : $count")
                        // This is where the work is completed
                        it.resume(Result.success(count))
                    }
                }

                val mConnectionListener = object : HealthDataStore.ConnectionListener {

                    override fun onConnected() {
                        Log.d(APP_TAG, "Health data service is connected.")
                        mReporter = StepCountReporter(mStore!!)
                        if (isPermissionAcquired) {
                            mReporter!!.start(mStepCountObserver)
                        } else {
                            Log.e(APP_TAG, "permissions not acquired")
                            it.resumeWithException(Exception("permissions not acquired"))
                        }
                    }

                    override fun onConnectionFailed(error: HealthConnectionErrorResult) {
                        Log.d(APP_TAG, "Health data service is not available.")
                        it.resumeWithException(Exception("Health data service is not available."))
                    }

                    override fun onDisconnected() {
                        Log.d(APP_TAG, "Health data service is disconnected.")
                        it.resumeWithException(Exception("Health data service is disconnected."))
                    }
                }
                mStore = HealthDataStore(appContext, mConnectionListener)
                mStore!!.connectService()
                // wait for mStepCountObserver.onChanged to be called

            }

            Result.success()
        } catch (error: Throwable) {
            Result.failure()
        }
    }

推荐阅读