android 使用Jetpack合成视图查看模型

pdsfdshx  于 2023-01-28  发布在  Android
关注(0)|答案(2)|浏览(130)

我正在使用ViewModelFactory获取视图模型示例,该示例将由我的jetpack组合视图使用。

class AchievementsScreenViewModelFactory() :
    ViewModelProvider.NewInstanceFactory() {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T = AchievementsScreenViewModel() as T
}

一旦示例化了我的视图模型,我就想执行一些操作。我目前把这些操作存储在视图模型构造函数中(就像一些firebase操作,检查是否找到了用户示例)。这是一个错误的做法吗?如果是,我应该怎么做?

constructor(context:Context) : this() {
        this.context=context
        mAuth= FirebaseAuth.getInstance()
        if(mAuth.currentUser!=null){
            triggerNavigateEvent(Screen.DashboardScreen)
        }
    }

因此,我面临的问题是,无论何时我使用视图模型工厂示例化视图的示例,然后当我从NavController弹出视图并返回时,视图模型工厂都会返回视图模型的相同示例,并且不会执行构造函数中存在的任务。
是否有办法在从NavController弹出屏幕时终止视图模型的示例?或者是否有其他方法?
我像这样从可组合屏幕调用视图模型

@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun LoginScreen(navController: NavHostController
){

    var viewModel:LoginScreenViewModel= viewModel(
        factory = LoginScreenViewModelFactory(LocalContext.current)
    )
    .
    .
    .
}

我正在使用谷歌伴奏导航库导航到屏幕。

AnimatedNavHost(
        navController = navController,
        startDestination = Screen.SplashScreen.route,
        enterTransition = { fadeIn(animationSpec = tween(1000), initialAlpha = 0f) },
        exitTransition ={ fadeOut(animationSpec = tween(1000), targetAlpha = 0f) }
    ){
        composable(
            route = Screen.LoginScreen.route
        ){
            LoginScreen(navController = navController)
        }
}
jk9hmnmh

jk9hmnmh1#

navigation-compose导航主机(在您的情况下为AnimatedNavHost)将在每次目的地改变时为目标目的地调用其composable函数,也就是说,当你导航到一个目的地时,以及当你往回导航时,这意味着你可以把你想要运行的代码放到你的ViewModel中的一个方法/函数中(而不是其构造函数),并使用LaunchedEffect组合对象来调用它。如果在调用LaunchedEffect组合对象时使用常量键,例如LaunchedEffect(Unit),则它将仅在进入组合对象时运行一次,在您的情况下,每次目标更改时运行一次。
将代码从VM构造函数移动到VM中的新函数

suspend fun callSomeApi() {
        // your code here
    }

并将LaunchedEffect(Unit)添加到要从中调用此新函数的组合对象中

@Composable
fun LoginScreen(navController: NavHostController){
    var viewModel: LoginScreenViewModel = viewModel(
        factory = LoginScreenViewModelFactory(LocalContext.current)
    )

    // called once every time this composable enters the composition
    LaunchedEffect(Unit) {    
        viewModel.callSomeApi()
    }
}
gxwragnw

gxwragnw2#

下面是我使用的一个示例

val viewModel = hiltViewModel<PokemonListVm>()
    • 用途**:
@Composable
fun PokemonListScreen(
    navController: NavController
) {

    val viewModel = hiltViewModel<PokemonListVm>()
    val lazyPokemonItems: LazyPagingItems<PokedexListEntry> = viewModel.pokemonList.collectAsLazyPagingItems()

    Surface(
        color = MaterialTheme.colors.background,
        modifier = Modifier.fillMaxSize()
    ) {

        Column {
            Spacer(modifier = Modifier.height(20.dp))
            PokemonBanner()
            PokemonSearch()
            PokemonLazyList(
                pokemonList = lazyPokemonItems,
                onItemClick = { entry ->
                    navController.navigate(
                        "pokemon_detail_screen/${entry.dominentColor.toArgb()}/${entry.pokemonName}"
                    )
                }
            )
        }
    }
}

相关问题