好的,我想我明白你的问题了。您有条件地将内容添加到后台堆栈,这使片段管理器处于奇怪的状态。
问题
您从 Main 开始,将扫描仪添加到后堆栈,但不添加产品。因此,当您按回键时,您会将 Scanner 从堆栈中弹出,但 Product 仍保留在 FragmentManager 中。这就是为什么每次扫描并返回时都会获取一个新实例的原因。我不清楚为什么会发生这种情况 - 看起来可能是 Android 错误?您正在替换片段,因此奇怪的是正在建立额外的实例。
一个解决方案将您的
changeFragment
实现更改为有条件地
弹出堆栈,而不是有条件地向其中添加内容。
fun changeFragment(fragment: Fragment, popStack: Boolean) {
if (keepStack) supportFragmentManager.popBackStack()
val transaction = supportFragmentManager.beginTransaction()
.replace(R.id.host_fragment, fragment,fragment::class.java.simpleName)
transaction.addToBackStack(null) // Always add the new fragment so "back" works
transaction.commit()
}
然后反转当前调用
changeFragment
的逻辑:
private fun addPurchase() {
// Pass false to not pop the main activity
(requireActivity() as MainActivity)
.changeFragment(ScanFragment.newInstance(), false)
}
还有...
override fun barcodeDetected(barcode: String) {
if (processingBarcode.compareAndSet(false, true)) {
// Pass true to pop the barcode that's currently there
(requireActivity() as MainActivity)
.changeFragment(PurchaseFragment.newInstance(barcode), true)
}
}
不仅如此,即使在片段中使用生命周期感知函数和
isVisible
方法,即使代码明显不可见,仍然会执行代码。
我有依赖于基本片段的片段,该片段在背面将片段从导航中弹出。我的主要问题是在第一个片段上,即使它应该关闭(并且确实)应用程序,但片段的
onviewcreated
一旦被销毁就会再次被调用,导致一些不应该执行的逻辑(某些 API 调用就我而言,协程以奇怪的状态结束)
我所做的是避免在该片段上调用popBackStack
,而是直接调用
finish
活动,这似乎已经解决了