【问题标题】:RecyclerView loses state on rotationRecyclerView 在旋转时失去状态
【发布时间】:2019-08-13 01:18:34
【问题描述】:

我正在使用 MVVM 设计模式、用于持久化数据和分页的空间制作一个笔记应用程序

问题是当我旋转我的设备时,它看起来好像保持状态不到一秒钟,然后 RecyclerView 向上滚动 我调试了我的代码,发现onChanged()被多次调用

这是我的代码

NoteRepository

override fun loadPagedNotes() : LiveData<PagedList<Note>> {
       val factory : DataSource.Factory<Int, Note> = mNotesDao.getNotes()
       val mNotesList = MutableLiveData<PagedList<Note>>()

       val notesList = RxPagedListBuilder(
           factory, PagedList.Config
               .Builder()
               .setPageSize(20)
               .setEnablePlaceholders(true)
               .build()
       ).buildFlowable(BackpressureStrategy.LATEST)

       mDisposables.add(
           notesList.subscribeOn(Schedulers.io())
               .observeOn(AndroidSchedulers.mainThread())
               .subscribe {
                   mNotesList.value = it
               }
       )
       return mNotesList
   }

NoteViewModel

fun loadPagedNotes() : LiveData<PagedList<Note>> {
        return mNoteRepository.loadPagedNotes()
    }

HomeActivity

class HomeActivity : AppCompatActivity() {

    private lateinit var mBinding : ActivityHomeBinding
    private val mViewModel : NoteViewModel by viewModel()

    override fun onCreate(savedInstanceState : Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_home)
        loadNotes()
    }


    private fun loadNotes() {
        mViewModel.loadPagedNotes()
            .observe(this,
                Observer {
                    if (it.isNotEmpty()) {
                        addNotesToRecyclerView(it)
                    }
                })
    }

    private fun addNotesToRecyclerView(list : PagedList<Note>?) {
        showRecyclerView()
        val adapter = PagedNoteListAdapter(this@HomeActivity)
        adapter.submitList(list)
        mBinding.notesRecyclerView.adapter = adapter
    }
}

【问题讨论】:

    标签: android kotlin android-room android-livedata android-paging


    【解决方案1】:

    当您旋转设备时,视图(片段)被销毁并重新创建,但 ViewModel 仍然存在。您遇到了麻烦,因为您的 ViewModel 从未利用此功能:相反,在(重新)创建您的视图时,它会导致 ViewModel 重新重新获取数据。每次调用 VM 的 loadPagedNotes 都会创建一个新的 LiveData 并返回它。您真的只想拥有一个,并且每次都返回对那个的引用。

    你为什么不把你的代码改成这样

    class NoteViewModel: ViewModel() {
        val pagedNotes = mNoteRepository.loadPagedNotes()
    }
    

    在你的活动中

    override fun onCreate(/*...*/) {
        mViewModel.pagedNotes.observe(this, Observer { addNotesToRecyclerView(it) 
    })
    

    另外,考虑将此val adapter = PagedNoteListAdapter(this@HomeActivity) 移动到活动的实例成员:val mAdapter = ...。这样一来,您的 addNotesToRecyclerView 代码将不会在每次您的存储库有更新时创建和绑定新适配器。

    class HomeActivity: /*...*/ {
        val mAdapter = PagedNoteListAdapter(this)
    
        override fun onCreate(...) {
            ...
            mBinding.notesRecyclerView.adapter = mAdapter
        }
    
        private fun addNotesToRecyclerView(list: PagedList<Note>) // You don't need the question mark since you're never calling the function except when you already know `list` isn't null) {
            mAdapter.submitList(list)
    }
    

    这可能是您遇到这种情况的另一个原因。

    此外,如果您仍然有不受欢迎的刷新,请查看 DiffUtil。它使您可以更新适配器的项目(如果它们单独更改),因此即使整个列表发生更改但某些元素保持不变,您也只会重绘已更改的元素而不重绘未更改的元素(例如,如果您添加了一项新项目,则不会重绘所有内容,而只会绘制一项新项目)

    【讨论】:

    • 乍一看,您的所有答案似乎都是正确的,我真的非常感谢您花费时间和精力来尝试使其发挥作用。问题是我正在使用MaterialSearchView 和@987654329 @我使用的是相同的addNotesToRecyclerView()我通过另一种方法解决了它并将搜索结果应用于同一个适配器谢谢您的时间。
    【解决方案2】:

    我不是 RxJava 专家,所以我不能说太多,但您是否尝试过从 ViewModelProviders 类中获取您的 ViewModel:

    myViewModel = ViewModelProviders.of(this)[MyViewModel::class.java]
    

    我相信以这种方式创建 ViewModel 实例可以让您的 ViewModel 存在于您的活动生命周期之外,并且可能有助于解决您的状态问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-02
      • 1970-01-01
      相关资源
      最近更新 更多