我正在使用 jetpack compose,我有一个表示为密封类的屏幕,它可以是三个可能值之一:Loading、Error 和 DataLoaded。现在 DataLoaded 是一个具有多个字段的数据类,我有一个 LaunchedEffect 块,我只想在特定字段更改时运行一些逻辑。我曾尝试使用该字段本身作为 LaunchedEffect 块的键,但该块会在任何字段更改时运行,我相信这是预期的,但我想知道是否有解决此问题的方法,或者我是否必须更改我的结构。在这里,我的 VM 为我的 ui 提供状态流服务。
class NowPlayingViewModel @Inject constructor(
private val audioRepository: AudioRepository,
) : ViewModel() {
private val errorFlow = MutableStateFlow<PlaybackException?>(null)
private val progressFlow = MutableStateFlow(0L)
private val playbackStateFlow = MutableStateFlow(-1)
private val nowPlayingFlow = audioRepository.getNowPlayingFlow()
val uiState =
combine(
nowPlayingFlow,
progressFlow,
playbackStateFlow,
errorFlow
) { nowPlaying, progress, playbackState, exception ->
when {
nowPlaying != null -> {
NowPlayingState.TrackLoaded(
nowPlaying.track,
nowPlaying.isPlaying,
nowPlaying.repeatMode,
nowPlaying.shuffleActive,
progress,
playbackState
)
}
exception != null -> {
val errorMessage = exception.localizedMessage ?: ""
NowPlayingState.ErrorLoadingTrack(Result.Error(errorMessage))
}
else -> null
}
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), initialValue = null)
}
我的组合是这样的:
@Composable
fun NowPlayingScreen(
uiState: NowPlayingState.TrackLoaded,
nowPlayingViewModel: NowPlayingViewModel,
goBack: () -> Unit
) {
val (track, isPlaying, repeatMode, isShuffleActive, progress, playbackState) = uiState
LaunchedEffect(key1 = track) {
Timber.d("LAUNCHED EFFECT")
}
}
还有 Track 类的样子:
@Entity
data class Track(
@PrimaryKey(autoGenerate = false)
val trackId: Long,
val trackTitle: String,
val trackLength: Int,
val artist: String,
val albumId: Long,
val contentUri: Uri?,
val thumbnail: Bitmap? = null,
val mimeType: String?,
val hasThumbnail: Boolean
)
如何让我的 LaunchedEffect 块仅在当前轨道发生变化时运行?现在它会在任何 uiState 字段更改时运行。
如果我自己没有尝试过,我猜想解构在
val (track, isPlaying, repeatMode, isShuffleActive, progress, playbackState) = uiState
是罪魁祸首。每当
uiState
变化时它总是会触发。
你试过使用
LaunchedEffect(uiState.track)
吗?
我猜可能是因为
Bitmap
在田径课上。虽然它看起来像正确的代码,但我们看不到您如何在 Track
处生成 AudioRepository
,也许它会获取有关此存储库的每个数据更改的位图,如 repeatMode
。不管这是不是问题,我建议考虑将uiState.track.trackId
传递给LaunchedEffect
,因为它有足够的信息来区分曲目。