Как поделиться одним и тем же экземпляром модели представления в навигации по созданию koinAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Как поделиться одним и тем же экземпляром модели представления в навигации по созданию koin

Сообщение Anonymous »

Я хочу использовать тот же экземпляр модели представления в koin в навигации по созданию реактивного ранца. Я знаю, что в koinViewModel() есть функция для получения экземпляра viewModel. Недавно я видел, что в документации Koin есть отдельный файл koin-androidx-compose-navigation, который предоставляет функцию koinNavViewModel().
build.gradle.kts
dependencies {

implementation("androidx.core:core-ktx:1.12.0")

implementation("io.insert-koin:koin-android:3.4.0")
implementation("io.insert-koin:koin-androidx-workmanager:3.4.0")
implementation("io.insert-koin:koin-androidx-compose:3.4.6")
implementation("io.insert-koin:koin-androidx-compose-navigation:3.4.6")

implementation(platform("androidx.compose:compose-bom:2023.06.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.foundation:foundation-layout")
implementation("androidx.compose.material:material")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.runtime:runtime")
implementation("androidx.compose.runtime:runtime-livedata")
implementation("androidx.compose.ui:ui-tooling")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose")
implementation("androidx.activity:activity-compose:1.7.0")
implementation("androidx.lifecycle:lifecycle-runtime-compose:$2.6.2")
implementation("androidx.navigation:navigation-compose:$2.6.0")

testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
}

Теперь я пытаюсь использовать одну модель представления на разных экранах. Когда я получаю некоторые данные в модели представления, я сохраняю их в SharedFlow и перехожу на другой экран с тем же экземпляром модели представления, который дает мне нулевую переменную.
MainActivity .kt
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SimpleComposeNavigationTheme {
SimpleNavigation()
}
}
}
}

Простая навигация
@Composable
fun SimpleNavigation(navController: NavHostController = rememberNavController()) {

NavHost(
navController = navController,
startDestination = navController.currentBackStackEntry?.destination?.route ?: "first_screen"
) {
composable("first_screen") {
val viewModel: FirstViewModel = koinNavViewModel()
Surface {
Column(Modifier.fillMaxSize()) {
Button(onClick = { viewModel.updateName("Hello world") }) {
Text(text = "Add Name")
}
Button(onClick = { navController.navigate("second_screen") }) {
Text(text = "Next Screen")
}
}
}
}
composable("second_screen") {
val viewModel: FirstViewModel = koinNavViewModel()
val firstName by viewModel.firstName.collectAsState()
LaunchedEffect(firstName){
println(">> $firstName")
}
Surface {
Column(Modifier.fillMaxSize()) {
firstName?.let { name -> Text(text = name) }
}
}
}
}
}

FirstViewModel.kt
class FirstViewModel : ViewModel() {
private val _firstName = MutableSharedFlow()
val firstName: SharedFlow = _firstName.asSharedFlow()

fun updateName(name: String) {
viewModelScope.launch {
_firstName.emit(name)
}
}
}

SampleApplication.kt
class SampleApplication : Application() {

override fun onCreate() {
super.onCreate()
initializeDependencyInjection()
}

private fun initializeDependencyInjection() {
startKoin {
androidLogger(Level.ERROR)
modules(
listOf(simpleModule)
)
}
}
}

val simpleModule = module {
viewModelOf(::FirstViewModel)
}

Каковы преимущества использования koinNavViewModel(), если мы не можем использовать один и тот же экземпляр на разных экранах создания посредством навигации.
Я знаю, что есть еще один вопрос по использованию другого класса для хранения всех этих данных и получения данных. Хочу лучше подходить через коин. Спасибо
ОБНОВЛЕНИЕ
Я не хочу создавать модель представления на глобальном уровне и передавать экземпляр в каждый из них. функция.
ОБНОВЛЕНИЕ 1
Я попробовал предложение Hiren-rafaliya и benjytec, и оно работает
@Composable
fun SimpleNavigation(navController: NavHostController = rememberNavController()) {

NavHost(navController = navController, startDestination = "screenA", route = "parentRoute") {
composable("screenA") {
// create backstack entry from parent route which was passed in NavHost
val backStackEntry = remember(it) { navController.getBackStackEntry("parentRoute") }
// pass the backstack entry as viewModelStoreOwner
val viewModel: MainViewModel = koinNavViewModel(viewModelStoreOwner = backStackEntry)
ScreenA(viewModel) {
navController.navigate("screenB")
}
}
composable("screenB") {
// create backstack entry from parent route which was passed in NavHost
val backStackEntry = remember(it) { navController.getBackStackEntry("parentRoute") }
// pass the backstack entry as viewModelStoreOwner
val viewModel: MainViewModel = koinNavViewModel(viewModelStoreOwner = backStackEntry)
ScreenB(viewModel) {
navController.navigate("screenA")
}
}
}
}

@Composable
fun ScreenA(viewModel: MainViewModel, onNavigate: () -> Unit) {
val firstName by viewModel.firstName
Column {
Text(text = "SCREEN A")
Text(text = "MainViewModel.firstname = $firstName")
Button(onClick = {
viewModel.updateName("ABC")
}) {
Text(text = "MainViewModel.firstname = ABC")
}
Button(onClick = onNavigate) {
Text(text = "Go to SCREEN B")
}
}
}

@Composable
fun ScreenB(viewModel: MainViewModel, onNavigate: () -> Unit) {
val firstName by viewModel.firstName
Column {
Text(text = "SCREEN B")
Text(text = "firstname = $firstName")
Button(onClick = {
viewModel.updateName("DEF")
}) {
Text(text = "MainViewModel.firstname = DEF")
}
Button(onClick = onNavigate) {
Text(text = "Go to SCREEN A")
}
}
}

class MainViewModel : ViewModel() {
private val _firstName = mutableStateOf(null)
val firstName: State = _firstName

fun updateName(name: String) {
viewModelScope.launch {
_firstName.value = name
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/779 ... navigation
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»