从 API 获取数据时,我在过滤 ViewModel 中的数据时遇到问题。我有一个 ViewModel (CharacterViewModel),它使用 getCharactersUseCase 检索数据。我想根据角色 ID 过滤这些数据,并在可组合项 (CharacterDetailScreen) 中观察过滤结果。但是,我没有得到预期的结果。
角色视图模型
@HiltViewModel
class CharacterViewModel @Inject constructor(
private val getCharactersUseCase: GetCharactersUseCase
) : ViewModel() {
private val _characterState: MutableStateFlow<PagingData<Character>> =
MutableStateFlow(value = PagingData.empty())
private val _characterDetailsState: MutableStateFlow<Character?> = MutableStateFlow(null)
val charactersState: MutableStateFlow<PagingData<Character>> get() = _characterState
val characterDetailsState: MutableStateFlow<Character?> get() = _characterDetailsState
init {
getCharacters()
}
private fun getCharacters() {
viewModelScope.launch {
getCharactersUseCase.execute(Unit)
.distinctUntilChanged()
.cachedIn(viewModelScope)
.collect {
_characterState.value = it
}
}
}
fun getCharacterDetails(characterID: String) {
Log.i("character"," character from viewmodel received id= ${characterID}")
// Collect the latest charactersState and then filter the character
viewModelScope.launch {
charactersState.collect { characters ->
characters
.filter { it.id == characterID }
.map { character ->
Log.i("character"," character from viewmodel id= ${character.id}")
_characterDetailsState.value = character
}
}
}
}
}
角色详情画面
@Composable
fun CharacterDetailScreen(
navController: NavController,
viewModel: CharacterViewModel = hiltViewModel(),
characterId: String
)
{
// Collect character details state
val characterDetailsState by viewModel.characterDetailsState.collectAsState()
LaunchedEffect(characterDetailsState) {
viewModel.getCharacterDetails(characterId)
}
// Use LaunchedEffect to trigger the getCharacterDetails call when the Composable is first launched
CharacterDetailsItem(characterDetailsState, characterId)
}
角色详情项目
@Composable
fun CharacterDetailsItem(character_: Character?, characterId: String){
Log.i("character"," character from details item ${character_?.name}")
val character by remember { mutableStateOf(character_) }
Box(modifier = Modifier.padding(top = 8.dp)) {
Card(
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
),
modifier = Modifier
.fillMaxWidth()
) {
Column {
Text(
text = characterId,
modifier = Modifier
.padding(16.dp),
textAlign = TextAlign.Center,
)
character?.name?.let {
Text(
text = it,
modifier = Modifier
.padding(16.dp),
textAlign = TextAlign.Center,
)
}
character?.gender?.let {
Text(
text = it,
modifier = Modifier
.padding(16.dp),
textAlign = TextAlign.Center,
)
}
}
}
}
}
日志猫
2023-11-17 12:01:19.709 5486-5486 character com.starwars.app I character from details item null
2023-11-17 12:01:19.740 5486-5486 character com.starwars.app I character from viewmodel received id= 631a02dc-ecf2-4636-8e59-d180766e52cf
2023-11-17 12:01:19.760 5486-5486 character com.starwars.app I character from details item null
2023-11-17 12:01:20.472 5486-5486 character com.starwars.app I character from details item null
2023-11-17 12:01:20.524 5486-5486 character com.starwars.app I character from details item null
我提供了 ViewModel (CharacterViewModel)、Composable (CharacterDetailScreen) 和用于显示详细信息的 Composable (CharacterDetailsItem) 的代码片段。如果您能深入了解 ViewModel 中的过滤逻辑可能导致的问题,我将不胜感激。
我尝试过的:
fun getCharacterDetails(characterID: String) {
Log.i("character", " character from viewmodel received id= ${characterID}")
// Collect the latest charactersState and then filter the character
viewModelScope.launch {
_characterDetailsState.value = Character("213","bday","e","g","h","hi","name","skin")
}
}
这样我就可以设置和获取值,但不能从charactersState或_characterState过滤值中设置和获取值。
我认为你不应该收集里面的状态
ViewModel
。如果您想通过搜索查询过滤州列表。
您可能需要考虑类似的解决方案:https://stackoverflow.com/a/72311648/7805359