我正在使用最新的Android体系结构组件构建应用程序。我正在将firebase firestore用作带有jetpack导航(底部导航)的数据库。我能够成功显示数据库中的数据。但是每当我旋转mt屏幕时,商店片段就会重新创建并向DB发出请求。
回购
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)
ViewModel
@ExperimentalCoroutinesApi
@InternalCoroutinesApi
class StoreViewModel(private val repository: DBInterface = Repo()) : ViewModel() {
fun getAllStores() = repository.getAllStores()
}
存储片段
@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))
}
}
}
主要活动(导航图)
@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())
}
}
每次它都会重新创建我的片段。我不想使用方法保存或保留任何视图。因为ViewModel用于保护屏幕旋转时的视图。请让我知道任何提示和技巧。在此先感谢;)
答案 0 :(得分:2)
Flow
本身不是有状态的-这是它与LiveData
之间的主要区别。这意味着collect
完成后,下一个collect
从头开始callbackFlow
。
这正是lifecycle-livedata-ktx
工件包含asLiveData()
扩展名的原因,该扩展名允许您在保持{的有状态(和生命周期)属性的同时,继续在存储库层使用Flow
{1}}用于您的用户界面:
LiveData
您将更改UI代码以继续使用@ExperimentalCoroutinesApi
@InternalCoroutinesApi
class StoreViewModel(private val repository: DBInterface = Repo()) : ViewModel() {
fun getAllStores() = repository.getAllStores().asLiveData()
}
和LiveData
。
科特林正在a shareIn
operation上进行研究,将允许您的observe()
保存ViewModel
的状态。这样一来,当调用Flow
的Fragment / Activity被销毁并重新创建时,您就可以在应用的所有层使用Flow
,而无需从头开始重新查询信息。
答案 1 :(得分:1)