当打开带有屏幕旋转更改的对话片段时,会多次调用观察器



我有一个活动,它在 OnCreate 中为视图模型中的 MutableLiveData 变量实现了一个观察器。

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
subscribeDialogFragmentManualInput()
}
private fun subscribeDialogFragmentManualInput() {
this.sharedViewModel.inputBarcode.observe(this) { inputValue ->
postInput(inputValue)
}
}

我的活动始终处于横向模式(清单中默认),当按下按钮时,将打开 DialogFragment 并将旋转更改为纵向,关闭时活动将返回到横向模式。

private fun showInvoiceInputDialog() {
val inputDialog = InvoiceInputDialogFragment
val transaction = supportFragmentManager.beginTransaction()
inputDialog.show(transaction, InvoiceInputDialogFragment.TAG)
}
class InvoiceInputDialogFragment : DialogFragment() {
lateinit var binding: DialogFragmentInvoiceInputBinding
private val sharedViewModel by sharedViewModel<ManualInvoiceInputViewModel>()
private var invoiceInput: String = ""
...

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
setStyle(
STYLE_NORMAL,
R.style.FullScreenDialog
)
binding = DataBindingUtil.inflate(
inflater,
R.layout.dialog_fragment_invoice_input,
container,
false
)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setViews()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
if(invoiceInput.isNotEmpty()) {
sharedViewModel.sendInputInvoice(invoiceInput)
}
}
private fun setViews() {
binding.btConfirmInput.setOnClickListener {
invoiceInput = binding.scannerManualInput.text
dismiss()
}
}
}

此流程使观察者多次触发,使我的应用程序具有和不受欢迎的行为,因为实时数据结果会打开一个对话框并多次显示。

我只想在对话框片段关闭后调用postInput方法一次。

谢谢!

LiveData默认设置为近循环逻辑。当视图更新时,这会引发一些问题LiveData然后LiveData将想要再次更新视图,从而创建无限循环。尽管您是通过激发Android Lifecycle重新创建您的Activity来间接执行此操作的,并且当重新创建时,它会附加另一个观察者,从而重新发出旧值。

您有 2 个选项:

保存对话框已在 savedInstanceState 中调用的事实Bundle

overide fun onSaveInstanceState(savedInstanceState : Bundle?) {
// Save the user's current game state
savedInstanceState.putBoolean("dialogCausedRecreate", dialogWasCreated);
super.onSaveInstanceState(savedInstanceState); 
} 
//in onCreate
this.sharedViewModel.inputBarcode.observe(this) { inputValue ->
if(!savedInstanceState.getBoolean("dialogCausedRecreate",false)){
postInput(inputValue)
}
}

创建一个新的包装类,该包装类可以跟踪是否发出。 这是一个例子 实时数据阻止在开始观察时接收最后一个值

接受的答案将让您将条形码包装在 Event 类中,这将允许您判断它之前是否已经发出。

最新更新