我应该选择从ViewModel中收集Flow还是直接在Compose中收集Flow ?



代码A在ViewModel,中收集Flow,使用MutableStateFlow将Flow转换为热流,然后在Compose中使用collectAsState()

代码B在Compose中收集Flow,并直接在Compose中使用collectAsState

代码A和代码B哪个更好?

在我看来,代码A转换流为ViewModel中的热流,它会保留内存和浪费资源,这是一个好方法吗?

代码

@Composable
fun BookListScreen(
viewModel: BookListViewModel,
...
) {
val booksListUiState by viewModel.uiState.collectAsState()
...
}

@HiltViewModel
class BookListViewModel @Inject constructor(
private val bookUseCase: BookUseCase
) : ViewModel() {
private var loadBooksJob: Job? = null

private val _uiState = MutableStateFlow(BookListUiState())
val uiState = _uiState.asStateFlow()
init {
loadBooks()
}
fun loadBooks() {
loadBooksJob?.cancel()
loadBooksJob = viewModelScope.launch {
bookUseCase.listBooks().collect { resultState ->
_uiState.update {
it.copy(bookListState = resultState)
}
}
}
}
...
}

override fun loadBooks(): Flow<ResultState<List<Book>>> {
...
}

代码B

@Composable
fun Greeting(
name: String,
mViewMode:SoundViewModel= viewModel()
) {
Column(

) {
val myResult by mViewMode.listRecord().collectAsState(initial =Result.Error(Exception()) )
..
}

@HiltViewModel
class SoundViewModel @Inject constructor(
private val aSoundMeter: RecordRepository
): ViewModel()
{
fun listRecord(): Flow<Result<List<MRecord>>> {
return  aSoundMeter.listRecord()
}
}

@Dao
interface  RecordDao { 
@Query("SELECT * FROM record_table ORDER BY createdDate desc")
fun listRecord():  Flow<List<RecordEntity>>
}

class RecordRepository @Inject constructor(private val mRecordDao:RecordDao): IRecordRepository {
override fun listRecord(): Flow<Result<List<MRecord>>> {      
...
}
}

InCode A,你保持一个流进入视图模型。因此,在用户旋转设备的情况下,该流将被保存。此外,如果在BookListScreen中重新组合,则不会调用loadBooks

代码BlistRecord在每次重组发生时被调用,因此每次屏幕被重绘时,你都在做一个数据库调用。由于您的数据库是本地的,因此损坏看起来并不那么严重,但如果您使用的是远程数据库(如Firebase或REST web服务),则此代码将在每次重组中执行网络调用,包括当您旋转设备或返回此屏幕时。

从Android开发者频道查看这个播放列表。特别是这个视频(它更专注于你的问题)。

最新更新