SavedStateHandle возвращает нулевые значения

У меня есть ActionBar значок меню, который открывает CategoryFragment. В этом фрагментеcategory объект SafeArgsаргумент передан из другого фрагмента. вCategoryFragment, Я храню categoryимя и идентификатор в общий фрагмент ViewModel в качестве SavedStateHandleценности. Я настроил его так, чтобы фрагмент использовал сохраненныйSavedStateHandleзначения для имени и идентификатора категории, когда это необходимо. Например, впервыеCategoryFragment использует объект категории, переданный из отправляющего фрагмента, но последующее создание CategoryFrgament будет использовать SavedStateHandle ценности.

Проблема в том, что после первого открытия CategoriesFragment а затем выйдите из приложения, нажав физическую кнопку возврата телефона или завершив приложение с помощью недавней кнопки телефона на панели навигации, теперь открывая CategoryFragmentнепосредственно при нажатии значка меню ActionBar отображается пустой экран. Это потому, что значения, возвращаемые изSavedStateHandleравны нулю. Как я могу это исправить?

Категория Фрагмент

class CategoryFragment : Fragment(), SearchView.OnQueryTextListener {

    lateinit var navController: NavController
    private var adapter: TasksRecyclerAdapter? = null
    private val viewModel: CategoryTasksViewModel by activityViewModels()
    private var fromCategoriesFragment: Boolean = false

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_category, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        navController = Navigation.findNavController(view)

        observerSetup()
        recyclerSetup()

        var searchView = category_tasks_searchview
        searchView.setOnQueryTextListener(this)

        fab_new_task.setOnClickListener {
            navController.navigate(R.id.action_categoryFragment_to_newTaskDialogFragment)
        }

        showTasks()
    }

private fun showTasks() {

        if(fromCategoriesFragment){

            PomoPlayObservablesSingleton.fromCategoriesFragment.onNext(false)

            if (!arguments?.isEmpty!!) {

                var args = CategoryFragmentArgs.fromBundle(arguments!!)
                category_title.text = args.category?.name

                var category = args.category
                viewModel.setPomoCategoryName(category.name)
                viewModel.setCategoryId(category.id)
                viewModel.searchTasksByCategoryId(category.id)

            }

        }
        else{
            category_title.text = viewModel.getPomoCategoryName()
            viewModel.searchTasksByCategoryId(viewModel.getCategoryId())

            Log.i("CategoryFrag-CatName", viewModel.getPomoCategoryName().toString())
            Log.i("CategoryFrag-CatId", viewModel.getCategoryId().toString())
        }
    }

    private fun observerSetup() {

        viewModel.getSearchTasksByCategoryIdResults().observe(this,androidx.lifecycle.Observer { tasks ->

            if(tasks.isNotEmpty()){

                adapter?.setTasksList(tasks.sortedBy { task -> task.name?.toLowerCase() })
                task_not_found_bubble.visibility = View.GONE
                task_not_found_text.visibility = View.GONE
            }
            else{
                task_not_found_bubble.visibility = View.VISIBLE
                task_not_found_text.visibility = View.VISIBLE
            }
        })

        PomoPlayObservablesSingleton.fromCategoriesFragment.subscribe {value -> fromCategoriesFragment = value}

    }

    private fun recyclerSetup() {
        adapter = context?.let { TasksRecyclerAdapter(it) }
        tasks_list?.layoutManager = LinearLayoutManager(context)
        tasks_list?.adapter = adapter
    }

    override fun onQueryTextSubmit(query: String?): Boolean {

        Log.i("Lifecycle-CatFragment", "onQueryTextSubmit() called")

        var q = query?.toLowerCase()?.trim()?.replace("\\s+".toRegex(), " ")
        setLastSearchQuery(q.toString())

        viewModel.searchTasksByName(viewModel.getLastSearchQuery().toString())

        return false
    }

    private fun setLastSearchQuery(lastSearchQuery: String) {
        viewModel.setLastSearchQuery(lastSearchQuery)
    }
}

КатегорияЗадачи ViewModel

class CategoryTasksViewModel(application: Application, state: SavedStateHandle) : AndroidViewModel(application) {

    private val repository: PomoPlayRepository = PomoPlayRepository(application)
    private val allCategories: LiveData<List<Category>>?
    private val allPomoTasks: LiveData<List<PomoTask>>?
    private val searchCategoriesByNameResults: MutableLiveData<List<Category>>
    private val searchCategoryByIdResults: MutableLiveData<Category>
    private val searchTasksByIdResults: MutableLiveData<PomoTask>
    private val searchTasksByNameResults: MutableLiveData<List<PomoTask>>
    private val searchTasksByCategoryIdResults: MutableLiveData<List<PomoTask>>

    private val savedStateHandle = state

    companion object{

        private const val LAST_SEARCH_QUERY = "lastSearchQuery"

    }

    init {
        allCategories = repository.allCategories
        allPomoTasks = repository.allPomoTasks
        searchTasksByIdResults = repository.searchTasksByIdResults
        searchTasksByNameResults = repository.searchTasksByNameResults
        searchTasksByCategoryIdResults = repository.searchTasksByCategoryIdResults
        searchCategoryByIdResults = repository.searchCategoriesByIdResults
        searchCategoriesByNameResults = repository.searchCategoriesByNameResults
    }

    fun setLastSearchQuery(lastSearchName: String){
        savedStateHandle.set(LAST_SEARCH_QUERY, lastSearchName)
    }

    fun getLastSearchQuery(): String?{
        return savedStateHandle.get<String>(LAST_SEARCH_QUERY)
    }

    fun setPomoCategoryName(name: String?){
        savedStateHandle.set("categoryName", name)
    }

    fun getPomoCategoryName(): String?{
        return savedStateHandle.get<String>("categoryName")
    }

    fun setCategoryId(id: Int){
        savedStateHandle.set("categoryId", id)
    }

    fun getCategoryId(): Int?{
        return savedStateHandle.get<Int>("categoryId")
    }

    fun insertTask(pomoTask: PomoTask?) {
        repository.insertTask(pomoTask)
    }

    fun deleteTask(pomoTask: PomoTask) {
        repository.deleteTask(pomoTask)
    }

    fun updateTask(pomoTask: PomoTask) {
        repository.updateTask(pomoTask)
    }


    fun searchTasksByName(name: String) {
        repository.searchTasksByName(name)
    }


    fun searchTasksById(pomoTaskId: Int){
        repository.searchTasksById(pomoTaskId)
    }

    fun searchTasksByCategoryId(categoryId: Int?){
        repository.searchTasksByCategoryId(categoryId)
    }

    fun getAllPomoTasks() : LiveData<List<PomoTask>>? {
        return allPomoTasks
    }

    fun getSearchTasksbyNameResults() : MutableLiveData<List<PomoTask>> {
        return searchTasksByNameResults
    }

    fun getSearchTasksByIdResults() : MutableLiveData<PomoTask> {
        return searchTasksByIdResults
    }

    fun getSearchTasksByCategoryIdResults() : MutableLiveData<List<PomoTask>> {
        return searchTasksByCategoryIdResults
    }

}

1 ответ

SavedStateHandleне был разработан, чтобы делать то, что вы от него ожидаете: это ...

... представляет собой карту ключ-значение, которая позволит вам записывать и извлекать объекты в сохраненное состояние и из него. Эти значения сохранятся после завершения процесса системой и останутся доступными через тот же объект.

Убит системой, а не в том случае, если пользователь умышленно закрывает приложение или даже уничтожает («уходит навсегда») фрагмент/активность, действующую в качестве его области. См. документацию по сохранению состояния пользовательского интерфейса — отклонение состояния пользовательского интерфейса по инициативе пользователя :

Предположение пользователя в этих случаях полного увольнения состоит в том, что он навсегда ушел от действия, и если они повторно откроют действие, они ожидают, что действие начнется с чистого состояния. Базовое поведение системы для этих сценариев отклонения соответствует ожиданиям пользователя — экземпляр действия будет уничтожен и удален из памяти вместе с любым сохраненным в нем состоянием и любой сохраненной записью состояния экземпляра, связанной с действием.

Возможно, сохраните информацию, которую вы ожидаете, чтобы выжить в вашем сценарии, в SharedPreferences .

Другие вопросы по тегам