配置更改不保存应用程序状态 MVVM

Posted

技术标签:

【中文标题】配置更改不保存应用程序状态 MVVM【英文标题】:Configuration Changes Not Save App State MVVM 【发布时间】:2022-01-21 18:27:50 【问题描述】:

我正在构建一个电影应用程序。有一个与父尺寸匹配的回收器视图,以及 1 个搜索操作按钮(SearchView)。

当我搜索电影时,一切正常,但是当我改变方向时,活动就失去了它的状态。 recyclerview 变空了,我需要重新搜索电影。

我正在使用 MVVM,但我知道它不会发生..

谢谢!

这是存储库:

class MainRepository 

   
    private val searchAfterMutableLiveData = MutableLiveData<List<Movie>>()
    private val apiService : GetFromApi = APIService.retrofitClientRequest
    private val apiKey = "censored"

    fun searchAfter(searchAfter : String) : MutableLiveData<List<Movie>>

        apiService.searchAfter(apiKey,searchAfter)?.enqueue(object : Callback<MovieListResult?> 
            override fun onResponse(
                call: Call<MovieListResult?>,
                response: Response<MovieListResult?>
            ) 

                if (response.isSuccessful)
                    searchAfterMutableLiveData.value = response.body()?.moviesResults
                    Log.e("SearchMovieListResults","Result: $searchAfterMutableLiveData.value")
                

            

            override fun onFailure(call: Call<MovieListResult?>, t: Throwable) 
                Log.e("SearchMovieListResults","Failed: $t.message")
            
        )

        return searchAfterMutableLiveData
    



这是 ViewModel:

class MainViewModel : ViewModel()

    fun getMovieBySearch(searchAfter : String) : LiveData<List<Movie>>
        return mainRepository.searchAfter(searchAfter)
    


这是 MainActivity:

class MainActivity : AppCompatActivity() 

    private val mainViewModel : MainViewModel by viewModels()
    private lateinit var mainRecyclerView : RecyclerView
    private lateinit var mainAdapter : MainRecyclerViewAdapter

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initRecyclerView()

    


    private fun initRecyclerView() 

        mainRecyclerView = findViewById(R.id.mainRecyclerView)
        mainRecyclerView.setHasFixedSize(true)
        mainRecyclerView.layoutManager = GridLayoutManager(this,1)

    

    override fun onCreateOptionsMenu(menu: Menu): Boolean 
        menuInflater.inflate(R.menu.main_menu,menu)

        val searchView = menu.findItem(R.id.menu_search_movie).actionView as androidx.appcompat.widget.SearchView

        searchView.queryHint = "Search By Name,Actor .."
        searchView.setOnQueryTextListener(object : androidx.appcompat.widget.SearchView.OnQueryTextListener 
            override fun onQueryTextSubmit(whileTextChange: String?): Boolean 

                //Clear SearchView
                searchView.isIconified = true
                searchView.setQuery("", false)
                searchView.onActionViewCollapsed()
                mainViewModel.getMovieBySearch(whileTextChange.toString()).observe(this@MainActivity,object : Observer<List<Movie>?> 
                    override fun onChanged(newList: List<Movie>?) 
                        if (newList != null) 

                            mainAdapter = MainRecyclerViewAdapter(newList)
                            mainRecyclerView.adapter = mainAdapter
                            //mainAdapter.changeCurrentList(newList)

                        
                    
                )

                return false
            

            override fun onQueryTextChange(whileTextChange: String?): Boolean 
                Log.e("onQueryTextChange","Text: $whileTextChange")
                return false
            
        )



        return true
    



【问题讨论】:

【参考方案1】:

您需要在视图模型中保存所需的状态。例如,

var persistedMovies = arrayListOf<Movie>()

当搜索返回有效响应时,

mainViewModel.persistedMovies = newList

现在列表作用域到视图模型,并且通过方向变化保持不变。

【讨论】:

嘿,我不明白如何将它保存在 viewModel 中,我确实喜欢这样:pastebin.com/W6GA58tw 但是现在当我搜索它时,它只是不停地加载。 当然,将第一行放入视图模型,将第二行放入链接的第 38 行。现在mainViewModel.persistedMovies 在活动的onCreate() 中可用。 嘿,是的,我可以访问它,但它不是实时数据或可变实时数据,所以我该如何使用它? 您想用它填充 UI,对吧?如何使用它真的取决于您……请注意,不需要新的搜索,它可以解决原始问题。 感谢您的回答,最后一个问题。因此,当我在搜索电影后旋转设备时,recyclerview 变为空,因为它再次调用 onCreate 但我还没有搜索任何内容,并且在 onCreate 中没有任何东西可以膨胀 recyclerview。但是,如果我有流行电影或任何我在 onCreate 中膨胀的开始列表怎么办?当我搜索一部电影然后旋转屏幕时,它会用流行电影列表而不是我搜索的内容来膨胀回收器视图。我该如何克服呢?谢谢!

以上是关于配置更改不保存应用程序状态 MVVM的主要内容,如果未能解决你的问题,请参考以下文章

iOS MVVM 处理初始视图状态

Android - MVVM 中 ViewModel 状态的最佳实践?

Docker容器怎样更改容器内应用程序的配置文件

Android - MVVM中ViewModel状态的最佳实践?

使用按钮更改样式并保存此状态

WPF 分享一种设置程序保存配置文件的方法