我试图获得一些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没有任何错误。所以我假设有一个作用域问题。但是这里到底出了什么问题?
2条答案
按热度按时间q8l4jmvw1#
感谢user @amanin解决方案是使回调
iterable()
函数也可挂起8ftvxx2r2#
要像这样从回调内部发出流值,应该使用
callbackFlow
,只需将flow { ... }
替换为callbackFlow { ... }
,将emit
替换为send
(或sendBlocking
,如果需要)。您可能还需要添加类似
awaitClose
的内容,以确保流在回调仍处于活动状态时保持打开状态。有关如何设置回调流的更多说明,请查看the docs。