我试图通过表达式绑定从我的XML文件在"android:onclick…"调用我的片段函数,但它不会工作。错误是片段没有附加到上下文。
MaterialAlertDialogBuilder (requireContext ())
让我头疼。
我如何给上下文片段?
关于这个话题,我看到过类似的问题,但没有一个对我有帮助。
任何帮助都非常感谢。
ItemDetailFragment.kt:
class ItemDetailFragment : Fragment() {
private lateinit var item: Item
private val viewModel: InventoryViewModel by activityViewModels {
InventoryViewModelFactory(
(activity?.application as InventoryApplication).database.itemDao()
)
}
private val navigationArgs: ItemDetailFragmentArgs by navArgs()
private var _binding: FragmentItemDetailBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentItemDetailBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val id = navigationArgs.itemId
binding.viewModel = viewModel
binding.fragment = ItemDetailFragment()
}
/**
* Displays an alert dialog to get the user's confirmation before deleting the item.
*/
fun showConfirmationDialog() {
MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(android.R.string.dialog_alert_title))
.setMessage(getString(R.string.delete_question))
.setCancelable(false)
.setNegativeButton(getString(R.string.no)) { _, _ -> }
.setPositiveButton(getString(R.string.yes)) { _, _ ->
deleteItem()
}
.show()
}
/**
* Called when fragment is destroyed.
*/
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
fragment_item_detail.kt:
<?xml version="1.0" encoding="utf-8"?><!--
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.example.inventory.InventoryViewModel" />
<variable
name="fragment"
type="com.example.inventory.ItemDetailFragment" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="@dimen/margin"
tools:context=".ItemDetailFragment">
<Button
android:id="@+id/delete_item"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin"
android:onClick="@{()->fragment.showConfirmationDialog()}"
android:text="@string/delete"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/sell_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
这是我得到的错误:
java.lang.IllegalStateException: Fragment ItemDetailFragment{e562873} (c6ab2144-3bdc-410b-91eb-e5668e8b617a) not attached to a context.
你不应该将片段实例作为数据绑定变量传递。
你可以在你的InventoryViewModel
中定义一个Boolean
可变的实时数据变量,并在它发生变化时显示对话框:
private val _showConfirmation = MutableLiveData(false)
val showConfirmation
get() = _showConfirmation
fun onShowConfirmation() {
_showConfirmation.value = true
}
fun onConfirmationShown() {
_showConfirmation.value = false
}
然后,在ItemDetailFragment
中为这个属性定义一个观察者:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val id = navigationArgs.itemId
binding.viewModel = viewModel
binding.executePendingBindings()
viewModel.showConfirmation.observe(viewLifecycleOwner) {
if (it) {
showConfirmationDialog()
viewModel.onConfirmationShown()
}
}
}
最后,从XML中删除fragment
变量并将Button
的onClick
更改为:
<Button
...
android:onClick="@{() -> viewModel.onShowConfirmation()}"
/>