android - ViewModel fragment 在屏幕旋转时重新创建

标签 android kotlin android-fragments kotlin-coroutines android-viewmodel

我正在使用最新的 android 架构组件构建一个应用程序。我正在使用 firebase firestore 作为带有喷气背包导航(底部导航)的数据库。我成功地能够显示来自数据库的数据。但是每当我旋转 mt 屏幕时,商店 fragment 都会重新创建并向 DB 发出请求。
repo

    override fun getAllStores() = callbackFlow<State<List<Store>>> {
    // Emit loading state
    send(State.loading())

    val listener = remoteDB.collection(Constants.COLLECTION_STORES)
        .addSnapshotListener { querySnapshot, exception ->
            querySnapshot?.toObjects(Store::class.java)?.let { store ->
                // Emit success state with data
                offer(State.success(store))
            }
            exception?.let {
                // emit exception with message
                offer(State.failed(it.message!!))
                cancel()
            }
        }
    awaitClose {
        listener.remove()
        cancel()
    }

}.catch {
    // Thrown exception on State Failed
    emit(State.failed(it.message.toString()))
}.flowOn(Dispatchers.IO)
查看型号
@ExperimentalCoroutinesApi
@InternalCoroutinesApi
class StoreViewModel(private val repository: DBInterface = Repo()) : ViewModel() {

fun getAllStores() = repository.getAllStores()

}
存储 fragment
@ExperimentalCoroutinesApi
@InternalCoroutinesApi
class StoreFragment : Fragment(R.layout.fragment_store) {
private lateinit var storeAdapter: StoreAdapter
private val viewModel: StoreViewModel by viewModels()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    (activity as MainActivity).supportActionBar?.title = getString(R.string.store_title)

    setUpRV()

    // get all stores
    lifecycleScope.launch {
        getAllStores()
    }

}

private suspend fun getAllStores() {
    viewModel.getAllStores().collect { state ->
        when (state) {
            is State.Loading -> {
                store_progress.show()
            }

            is State.Success -> {
                storeAdapter.differ.submitList(state.data)
                store_progress.animate().alpha(0f)
                        .withEndAction {
                            store_rv.animate().alpha(1f)
                            store_progress.hide()
                        }

            }
            is State.Failed -> {
                store_progress.hide()
                activity?.toast("Failed! ${state.message}")
            }
        }
    }
}

private fun setUpRV() {
    storeAdapter = StoreAdapter()
    store_rv.apply {
        adapter = storeAdapter
        addItemDecoration(SpacesItemDecorator(16))
    }
}
}
主要 Activity (导航图)
@InternalCoroutinesApi
@ExperimentalCoroutinesApi
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar)

    // init bottom navigation
    bottom_navigation.setupWithNavController(nav_host_fragment.findNavController())
   
}
}
每次它重新创建我的 fragment 。我不想使用方法保存或保留任何 View 。因为 ViewModel 用于保护屏幕旋转时的 View 。请让我知道任何提示和技巧。提前致谢 ;)

最佳答案

Flow本身不是有状态的——这是它和 LiveData 之间的关键区别。 .这意味着在您的 collect 之后完成,下一个 collect开始 callbackFlow从头开始。
这正是 lifecycle-livedata-ktx 的原因。工件包含 asLiveData() 允许您继续使用 Flow 的扩展程序在存储库层,同时保持 LiveData 的状态(和生命周期)属性对于您的用户界面:

@ExperimentalCoroutinesApi
@InternalCoroutinesApi
class StoreViewModel(private val repository: DBInterface = Repo()) : ViewModel() {
    fun getAllStores() = repository.getAllStores().asLiveData()
}
您将更改您的 UI 代码以继续使用 LiveDataobserve() .
Kotlin 正在开发 a shareIn operation允许您的ViewModel保存 Flow 的状态.这将允许您使用 Flow当调用 collect 的 Fragment/Activity 时,无需从头开始重新查询信息被销毁并重新创建。

关于android - ViewModel fragment 在屏幕旋转时重新创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63104545/

相关文章:

android - 如何在 Activity 中使用 navGraphViewModels(不在 Fragment 中)

android - EndlessAdapter 只加载一页

java - 使用 RxJava 将数据从 ViewModel 移动到 Fragment

android - 用于更改语言的 LocaleManager 在 Marshmallow 设备中不起作用

androidx.navigation 库更新到 2.2.2 版本发布构建问题

java - 在 Android EditText 中,有没有办法强制每个字符为小写?

java - 使用opencv java检测图像中文档的边界

c# - 如何在 OncreateView 中运行一些异步的东西?

android - 在同一 Activity 中按下后退键,将一个 viewpager 的 fragment 替换为另一个 viewpager 的 fragment

java - 使用 Fast-Video-View 自动启动视频