使用以数据类字段为键的 LaunchedEffect

问题描述 投票:0回答:2

我正在使用 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 字段更改时运行。

android android-jetpack-compose android-jetpack
2个回答
0
投票

如果我自己没有尝试过,我猜想解构在

val (track, isPlaying, repeatMode, isShuffleActive, progress, playbackState) = uiState

是罪魁祸首。每当

uiState
变化时它总是会触发。

你试过使用

LaunchedEffect(uiState.track)
吗?


0
投票

我猜可能是因为

Bitmap
在田径课上。虽然它看起来像正确的代码,但我们看不到您如何在
Track
处生成
AudioRepository
,也许它会获取有关此存储库的每个数据更改的位图,如
repeatMode
。不管这是不是问题,我建议考虑将
uiState.track.trackId
传递给
LaunchedEffect
,因为它有足够的信息来区分曲目。

© www.soinside.com 2019 - 2024. All rights reserved.