首页 > 解决方案 > 如何使用不同的视图模型获得不同的状态?

问题描述

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

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

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

我不知道我该怎么做。

我在想我可以让我的登录屏幕在一种状态管理器中,它将用户界面引导到正确的屏幕,就像这样

@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进行某种神奇的依赖注入,然后将所有视图模型放入 aViewModelManagerMainActivity,然后在登录成功时将其注入Tokenrepositorieseach中。viewmodel

@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)
                }
            }
        }
    }
}

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

标签: androidkotlinandroid-jetpack-composedagger-hilt

解决方案


问题:您想与所有视图模型共享一个值(令牌)

您检索到的令牌AuthViewModel并需要将其共享给其他视图模型

当令牌更改时,您可以使用datastore Preferences查看实现来更改其他视图模型中的数据

每当值发生变化时,数据存储首选项都会为您提供值流

创建 DatastoreManager 类

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

@Singleton
class DatastoreManager @Inject constructor(@ApplicationContext context: Context) {

    private val dataStore = context.dataStore

    val dataFlow = dataStore.data
        .map { preferences ->
            val token = preferences[PreferencesKeys.TOKEN]
        }

    suspend fun updateToken(token: String) {
        dataStore.edit { preferences ->
            preferences[PreferencesKeys.TOKEN] = token
        }
    }

    private object PreferencesKeys {
        val TOKEN = preferencesKey<String>("token")
    }
}

在 AuthViewModel

登录后注入DatastoreManager并设置token

datastore.updateToken(newToken)

在其他 ViewModel 中

注入 DatastoreManager 并使用它的值

//this is a flow of tokens and will recive the token when you set it
val token = datastore.token
// if you are not familiar with flows and using only LiveData
val token = datastore.token.asLiveData()

// use the token to get the data from backend
val data = token.map {
    // this code will trigger every time the token changes
    yourGetDataFromBackendFunction(it)
}

推荐阅读