将调用 Fragment 使用的 ViewModel 共享给 viewModels 使用的 DialogFragment

Share ViewModel used by calling Fragment to DialogFragment using by viewModels

我有一个 SearchFragment,代码如下。

@AndroidEntryPoint
class SearchFragment :
    Fragment(),
    View.OnClickListener {
    ...
    private var _binding: FragSearchBinding? = null
    private val binding get() = _binding as FragSearchBinding
    private val viewmodel by viewModels<SearchViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    )
        : View {
        _binding = FragSearchBinding.inflate(inflater, container, false)
        binding.fragSearchSearchResultFilter.setOnClickListener(this)
        return binding.root
    }

    ...

    private fun showFilterDialog() {
        val dialog = FilterBottomSheetDialogFragment.newInstance()
        dialog.show(parentFragmentManager, "filter_bsd_tag")
    }
    ...
}

我正在使用 SearchFragment 显示 FilterBottomSheetDialogFragment。我想将 SearchFragment 的 ViewModel 传递给 DialogFragment。我的 FilterBottomSheetDialogFragment.

有这个代码
@AndroidEntryPoint
class FilterBottomSheetDialogFragment :
    BottomSheetDialogFragment(),
    View.OnClickListener {
    companion object {
        fun newInstance() = FilterBottomSheetDialogFragment()
        private const val TAG_SELECTION_DIALOG = "tag_selection_dialog"
    }

    private var _binding: BsdFilterBinding? = null
    private val binding get() = _binding as BsdFilterBinding
    private val viewmodel: SearchViewModel = ???
}

我试过了

private val viewmodel by viewModels<SearchViewModel>(ownerProducer = { this.requireParentFragment() })

上面的方法不起作用,因为它只是创建了一个新的 ViewModel 实例。

我也试过了

private val viewmodel: SearchViewModel by lazy {
    ViewModelProvider(requireParentFragment()).get(SearchViewModel::class.java)
}

上面的错误提示无法创建 SearchViewModel 实例。我的 SearchViewModel 有这个构造函数。

@HiltViewModel
class SearchViewModel @Inject constructor(
    private val courseRepository: CourseRepository
) : ViewModel()

如何在不使用构造函数参数的情况下将 SearchViewModel 传递给 DialogFragment

你错了,实际上是你在显示对话框时使用的片段管理器。目前您正在使用 parent 片段管理器,而您的对话框应该作为显示它的片段的子片段存在。

所以你应该使用:

dialog.show(childFragmentManager, "filter_bsd_tag")

这将确保

viewModels<SearchViewModel>(ownerProducer = { requireParentFragment() })

指的是SearchFragment.