返回时屏幕的重置状态,但不向前

问题描述 投票:0回答:1
在我的应用程序中,我有3个屏幕:Queryscreen,BookListsCreen和bookdetailsscreen。每个都有一个由ViewModel管理的Uistate类。屏幕之间的导航是使用NavHost进行的。

我应用背后的逻辑是:

  • Queryyscreen:

    我输入一本书,我想搜索并按搜索。我从ViewModel中调用该函数,该函数从服务器中获取书籍列表并导航到BookListsCreen.

    BookListsCreen
  • :显示获取的书籍列表,当用户单击一本书时,称为viewModel的函数the函数,该功能获取了有关该书的更多详细信息,并导航到BookDetailsscreen.
  • BookDetailsscreen
    :显示有关此书之前获取的详细信息。

  • 当我从第一个屏幕上导航时,我会相应地更新状态,并且我的应用程序的行为应应有的。我面临的问题是用于后退导航。假设我在

    书bookdetails中,然后回到bookList

    。这意味着我应该在
  • 书bookdetailsuistate
.

中进行searchBooks()对于booklist而言,同一件事。当我回到

QueryScreen
时,我应该在书booklistuistate.

中设置

searchBook()最好的方法是什么?假设我有20个屏幕,每个屏幕上都有一个旗帜,以跟踪我是否要回去。 如果您可以向我解释两种方法,我将感激不已,谢谢!! 这些是我的州课:

val book: Book = null
这是我在屏幕之间执行导航的方式:

val books: List<Book> = emptyList()

这是我的ViewModel类:

data class QueryUiState( val query: String = "", val isFetchingBooks: Boolean = false, val errorMessage: String? = null ) data class BookListUiState( val books: List<Book> = emptyList(), val isFetchingBook: Boolean = false, val errorMessage: String? = null, val selectedBook: Book? = null ) data class BookDetailsUiState( val book: Book? = null )
    

我在这里看到两种可能的方法。 aptiona

您可以尝试使用

    object BookshelfDestinations {
        const val QUERY_ROUTE = "query"
        const val BOOK_LIST_ROUTE = "bookList"
        const val BOOK_DETAILS_ROUTE = "bookDetails"
    }
    
    @OptIn(ExperimentalMaterial3Api::class)
    @Composable
    fun BookshelfApp(
        appContainer: AppContainer,
        navController: NavHostController = rememberNavController(),
        modifier: Modifier = Modifier
    ) {
        Scaffold { innerPadding ->
            BookshelfNavHost(
                appContainer = appContainer,
                navController = navController,
                modifier = modifier.padding(innerPadding)
            )
        }
    }
    
    @Composable
    fun BookshelfNavHost(
        appContainer: AppContainer,
        navController: NavHostController,
        modifier: Modifier = Modifier
    ) {
        val viewModel: AppViewModel =
            viewModel(factory = AppViewModel.AppViewModelFactory(appContainer.bookshelfRepository))
    
        NavHost(
            navController = navController,
            startDestination = BookshelfDestinations.QUERY_ROUTE,
            modifier = modifier
        ) {
            composable(route = BookshelfDestinations.QUERY_ROUTE) {
                QueryScreen(
                    viewModel = viewModel,
                    onSearch = {
                        navController.navigate(BookshelfDestinations.BOOK_LIST_ROUTE)
                    }
                )
            }
            composable(route = BookshelfDestinations.BOOK_LIST_ROUTE) {
                BookListScreen(
                    viewModel = viewModel,
                    onBookClicked = {
                        navController.navigate(BookshelfDestinations.BOOK_DETAILS_ROUTE)
                    }
                )
            }
            composable(route = BookshelfDestinations.BOOK_DETAILS_ROUTE) {
                BookDetailsScreen(
                    viewModel = viewModel
                )
            }
        }
    }
navigation android-jetpack-compose state
1个回答
0
投票

class AppViewModel(private val repository: BookshelfRepository) : ViewModel() { private val _queryUiState = MutableStateFlow(QueryUiState()) val queryUiState: StateFlow<QueryUiState> = _queryUiState.asStateFlow() private val _bookListUiState = MutableStateFlow(BookListUiState()) val bookListUiState: StateFlow<BookListUiState> = _bookListUiState.asStateFlow() private val _bookDetailsUiState = MutableStateFlow(BookDetailsUiState()) val bookDetailsUiState: StateFlow<BookDetailsUiState> = _bookDetailsUiState.asStateFlow() init { Log.d("AppViewModel", "App view model initialized!") } fun onQueryChanged(query: String) { _queryUiState.value = _queryUiState.value.copy(query = query) } fun onBookSelected(book: Book) { _bookListUiState.value = _bookListUiState.value.copy(selectedBook = book) searchBook() } fun searchBooks() { viewModelScope.launch { _queryUiState.value = _queryUiState.value.copy(isFetchingBooks = true) try { val result = repository.getBooks(_queryUiState.value.query) when(result) { is BookshelfResult.Success -> { _bookListUiState.value = _bookListUiState.value.copy(books = result.data) } is BookshelfResult.Error -> { _queryUiState.value = _queryUiState.value.copy(errorMessage = result.exception.message) } } } catch (e: Exception) { _queryUiState.value = _queryUiState.value.copy(errorMessage = e.message) } finally { _queryUiState.value = _queryUiState.value.copy(isFetchingBooks = false) } } } fun searchBook() { viewModelScope.launch { _bookListUiState.value = _bookListUiState.value.copy(isFetchingBook = true) try { val result = repository.getBook(_bookListUiState.value.selectedBook!!.id) when(result) { is BookshelfResult.Success -> { _bookDetailsUiState.value = _bookDetailsUiState.value.copy(book = result.data) } is BookshelfResult.Error -> { _bookListUiState.value = _bookListUiState.value.copy(errorMessage = result.exception.message) } } } catch (e: Exception) { _bookListUiState.value = _bookListUiState.value.copy(errorMessage = e.message) } finally { _bookListUiState.value = _bookListUiState.value.copy(isFetchingBook = false) } } } class AppViewModelFactory(private val appRepository: BookshelfRepository) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(AppViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return AppViewModel(appRepository) as T } throw IllegalArgumentException("Unknown ViewModel class") } } }

然后,在你的

BackHandler BookDetailsScreen( viewModel: AppViewModel, onBack: () -> Unit ) { `BackHandler` { viewModel.resetBook() onBack() } }

toption b(建议)

我认为更干净的是为您的ViewModel选择适当的
Scope。当前,您的ViewModel不在NAVHOST之外,因此范围为活动。如果您有三个较小的ViewModels,则可以将它们调整到Navgraph中的目的地,然后每当您离开此目的地时将它们重置。 您可以尝试这样的代码:

NavHost

功能是以下依赖性中包含的便利函数:

composable(route = BookshelfDestinations.BOOK_DETAILS_ROUTE) {
    BookDetailsScreen(
        viewModel = viewModel,
        onBack = {
            navController.popBackStack()
        }
    )
}

它会自动生成一个ViewModel实例,而无需手动工厂类别。
,然后,您可以使用“官方文档”中所述的导航参数将所需的数据(例如书ID)从一个目的地传递到下一个目的地。还可以查看

nevigation document

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.