kotlin 获得“只能调用暂停功能......”流量错误

h7wcgrx3  于 2023-01-26  发布在  Kotlin
关注(0)|答案(2)|浏览(145)

我试图获得一些React式编程和使用流的知识,因此我从contact类中取出了一个方法,并尝试对其进行一些重写,然后使用流来发出数据

val getMCxContactsFlow: Flow<MCxContact> = flow {
        val contact: MCxContact? = null
        val uri = RawContacts.CONTENT_URI
            .buildUpon()
            .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName)
            .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType)
            .build()

        val cursor = contentResolver.query(
            uri,
            arrayOf(Contacts._ID),
            null,
            null,
            null
        )
        getCursorInformation(cursor) { result ->
            result.apply {
                try {
                    val id = getStringOrNull(getColumnIndex(Contacts._ID))
                        ?: throw Exception("Cant find contact ID")
                    Log.d(TAG, id)
                    val query = contentResolver.query(
                        Data.CONTENT_URI,
                        null,
                        "${Data.RAW_CONTACT_ID} =?",
                        arrayOf(id),
                        null
                    )
                    val contacts = getContactFromQuery(query)
                    emit(contacts) // The Emit with the Error
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
        emit(contact!!) //This emit with the fake contact from first line works
    }

    private fun getCursorInformation(
        cursor: Cursor?,
        iterator: (cursor: Cursor) -> Unit
    ) {
        if (cursor == null) throw Exception("getCursorInformation: cursor is null")
        else {
            cursor.apply {
                if (count > 0) {
                    while (moveToNext()) iterator(this)
                } else {
                    throw Exception("Cursor data is empty")
                }
                close()
            }
        }
    }

但是Android在发射时给了我一个错误:Suspension functions can be called only within coroutine body末端的emit没有任何错误。所以我假设有一个作用域问题。但是这里到底出了什么问题?

q8l4jmvw

q8l4jmvw1#

感谢user @amanin解决方案是使回调iterable()函数也可挂起

private suspend fun getCursorInformation(
        cursor: Cursor?,
        iterator: suspend (cursor: Cursor) -> Unit
    ) {
        if (cursor == null) throw Exception("getCursorInformation: cursor is null")
        else {
            cursor.apply {
                if (count > 0) {
                    while (moveToNext()) iterator(this)
                } else {
                    throw Exception("Cursor data is empty")
                }
                close()
            }
        }
    }
8ftvxx2r

8ftvxx2r2#

要像这样从回调内部发出流值,应该使用callbackFlow,只需将flow { ... }替换为callbackFlow { ... },将emit替换为send(或sendBlocking,如果需要)。
您可能还需要添加类似awaitClose的内容,以确保流在回调仍处于活动状态时保持打开状态。有关如何设置回调流的更多说明,请查看the docs

相关问题