Android中Kotlin Flow collect耗时过长问题求助
Flow从Room数据库收集数据耗时异常,LiveData无此问题的排查与解决
我的Android应用用Room做本地数据库,有个从服务器拉数据更新本地库的函数。这个函数运行时,用Flow从数据库查数据会特别慢,但换成LiveData就正常。相关代码如下:
DAO代码
@Transaction @Query("SELECT * FROM tbl WHERE id=:id") fun getData(id: String): Flow<Entity?>
仓库代码
fun getData(id: String): Flow<Entity?> { return dao.getData(id).map { it?.toModel() } }
Fragment代码
lifecycleScope.launch() { repo.getData(args.id) .flowWithLifecycle(viewLifecycleOwner.lifecycle) .distinctUntilChanged() .collect { data -> data?.let { setData(data) } } }
问题原因分析
- @Transaction注解拖慢了Flow:DAO里的
getData加了@Transaction,Room的事务机制会让Flow的收集操作一直等更新事务完成才能执行,导致阻塞耗时。而LiveData的内部实现不会被这种事务阻塞。 - 线程调度没明确:Room的Flow默认在IO线程发射数据,但如果后续操作没指定合适的调度器,或者更新操作和查询操作抢占线程资源,也会导致耗时增加。
解决办法
去掉多余的@Transaction
单条查询根本不需要事务支持,直接删掉@Transaction就行:@Query("SELECT * FROM tbl WHERE id=:id") fun getData(id: String): Flow<Entity?>给Flow指定IO线程调度
在仓库层明确把数据库查询和数据转换放到IO线程,避免和主线程或更新操作冲突:import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.flowOn fun getData(id: String): Flow<Model?> { return dao.getData(id) .map { it?.toModel() } .flowOn(Dispatchers.IO) }另外,服务器更新本地库的函数也要确保在
Dispatchers.IO线程执行,别和查询抢资源。优化更新事务的效率
如果更新本地库的函数用了@Transaction,尽量简化事务内的操作,别让它长时间占用数据库锁。比如把大事务拆成小事务,或者优化SQL更新语句的性能。
内容的提问来源于stack exchange,提问作者Ali Zarei
相关产品推荐
相关产品推荐

