如何才能使不同的状态具有不同的视图模型? [英] How can I have different states with different viewmodels?

查看:19
本文介绍了如何才能使不同的状态具有不同的视图模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个应用程序,用户首先需要登录才能从后端获得许多不同的数据。(多个端点)

所以我有一个用于登录的视图模型,而我有许多用于所有其他数据的视图模型。

其他视图模型需要第一个视图模型中的令牌才能从后端获取数据。

我不知道如何才能做到这一点。

我在想,我可以在某种状态管理器中使用登录屏幕,它会将UI定向到正确的屏幕,如下所示

@ExperimentalComposeUiApi
@Composable
fun LoginState(vm: AuthViewModel, nc: NavController) {
    val token by vm.token.collectAsState()
    when (token) {
        is Resource.Loading -> {
            LoadingScreen()
        }
        is Resource.Success -> {
            Scaffold(vm = vm)
        }
        is Resource.Error -> {
            LoginScreen(vm = vm)
        }
    }
}

但我必须在Scaffold中创建视图模型,这是一个可组合的函数,这是不可能的。

另一种想法是使用Hilt进行某种魔术依赖注入,然后将所有的view Model放入MainActivity中的ViewModelManager,登录成功后再将Token注入到每个viewmodelrepositories中。

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    private val authViewModel: AuthViewModel by viewModels()
    private val userViewModel: UserViewModel by viewModels()
    private val venueViewModel: VenueViewModel by viewModels()
    private val eventViewModel: EventViewModel by viewModels()

    private val viewModelManager = ViewModelManager(
        userViewModel = userViewModel,
        authViewModel = authViewModel,
        venueViewModel = venueViewModel,
        eventViewModel = eventViewModel,
    )

    @ExperimentalMaterialApi
    @ExperimentalComposeUiApi
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MoroAdminTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    ScaffoldExample(viewModelManager)
                }
            }
        }
    }
}

但是,我不知道如何做到这一点,或者这是否可能-或者是一个好的解决方案。

推荐答案

但我必须在Scaffold内创建视图模型,这是一个可组合的函数,而这是不可能的。

这不是真的。您不必在活动中创建视图模型。

在任何组合中都可以使用viewModel()

返回现有的ViewModel或在给定的所有者(通常是片段或活动)中创建一个新的,默认为LocalViewModelStoreOwner提供的所有者。

所以您不需要任何ViewModelManager。在任何组合中,您都可以将viewModel()与相应的类一起使用。如果您使用的是Hilt,则应改用hiltViewModel():它还会初始化您的注射。

@Composable
fun AuthScreen(viewModel: AuthViewModel = hiltViewModel()) {

}

或类似于:

@Composable
fun VenueScreen() {
    val viewModel: VenueViewModel = hiltViewModel()
}

第一种方法将允许您使用模拟视图模型轻松测试屏幕,而无需在生产代码中传递任何参数。

view models documentationhilt documentation中查看有关视图模型的详细信息


关于您的令牌问题,您可以通过注射传递。我不认为您的视图模型真的需要令牌,也许您应该有一些网络管理器来使用令牌来发出请求。并且此网络管理器应使用某个令牌提供商的注入。

这篇关于如何才能使不同的状态具有不同的视图模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆