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 .