android - 如何使用不同的视图模型获得不同的状态?
问题描述
我正在制作一个应用程序,用户首先需要登录才能从后端获取大量不同的数据。(许多端点)
所以我有一个用于登录的视图模型,我有很多用于所有其他数据的视图模型。
其他视图模型需要来自第一个视图模型的令牌才能从后端获取数据。
我不知道我该怎么做。
我在想我可以让我的登录屏幕在一种状态管理器中,它将用户界面引导到正确的屏幕,就像这样
@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进行某种神奇的依赖注入,然后将所有视图模型放入 aViewModelManager
中MainActivity
,然后在登录成功时将其注入Token
到repositories
each中。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)
}
}
}
}
}
但是我不知道如何做到这一点,或者它是否可能 - 或者一个好的解决方案。
解决方案
问题:您想与所有视图模型共享一个值(令牌)
您检索到的令牌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)
}
推荐阅读
- algorithm - 如何选择仅包含已知单词的句子的数据结构
- git - 隐藏当前分支和主分支之间的差异以将其应用于旧提交
- python - 如何处理空的“DataFrame”:没有数字数据来绘制错误以在图表上获取字符串
- flutter - 流控制器未注册接收器事件颤动
- angular-forms - 如何以角度形式实现速记验证?
- python - Django Rest Framework - 如何对 MSSQL 存储过程中的数据进行建模和序列化
- python - Django 无法读取其他应用程序的模型
- python - 使用 Python 和 Selenium 将 APK 上传到解释为 URL 的网页
- arrays - 在 bash 中对带有空格的数组进行切片
- imagemagick - 在 ImageMagick 的循环中使用复合