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

Ric*_*ard 2 viewmodel android-fragments kotlin android-viewmodel android-ktx

我有一个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")
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我正在展示一个FilterBottomSheetDialogFragment使用它的方法SearchFragment。我想将 ViewModel 传递SearchFragmentDialogFragment. 我的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 = ???
}
Run Code Online (Sandbox Code Playgroud)

我努力了

private val viewmodel by viewModels<SearchViewModel>(ownerProducer = { this.requireParentFragment() })
Run Code Online (Sandbox Code Playgroud)

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

我也尝试过

private val viewmodel: SearchViewModel by lazy {
    ViewModelProvider(requireParentFragment()).get(SearchViewModel::class.java)
}
Run Code Online (Sandbox Code Playgroud)

上面的内容不适用于SearchViewModel无法创建实例的错误。我的SearchViewModel有这个构造函数。

@HiltViewModel
class SearchViewModel @Inject constructor(
    private val courseRepository: CourseRepository
) : ViewModel()
Run Code Online (Sandbox Code Playgroud)

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

Hen*_*ist 7

您在这里的错误实际上是您在显示对话框时使用的片段管理器。当前您正在使用片段管理器,而您的对话框应作为显示它的片段的子片段存在。

所以你应该使用:

dialog.show(childFragmentManager, "filter_bsd_tag")
Run Code Online (Sandbox Code Playgroud)

这将确保

viewModels<SearchViewModel>(ownerProducer = { requireParentFragment() })
Run Code Online (Sandbox Code Playgroud)

SearchFragment.