1

我有一个带有播客 RecyclerView 的屏幕,当您单击其中一个时,它会将您带到该特定播客的详细信息屏幕。使用 Kodein 进行 ViewModel 注入,我如何将从列表片段中单击的播客的 id 传递给详细片段的 ViewModel,以便可以从 API 中获取它?

详细 ViewModel 的结构如下:

class PodcastDetailViewModel internal constructor(
    private val podcastRepository: PodcastRepository,
    podcastId: String = ""
): ViewModel() {
    // viewmodel stuff
}

细节片段如下所示:

class PodcastDetailFragment : ScopedFragment(), KodeinAware {
    override val kodein by closestKodein()
    private val args: PodcastDetailFragmentArgs by navArgs()
    private val viewModelFactory: PodcastDetailViewModelFactory by kodein.newInstance { PodcastDetailViewModelFactory(args.podcastId, instance()) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel = viewModelFactory.create(PodcastDetailViewModel::class.java)
    }

    // other stuff
}

这就是我从列表中导航到详细信息屏幕的方式:

private fun navigateToPodcastDetailFragment(podcastId: String) {
        val args = Bundle()
        args.putString("podcast_id", podcastId)

        val directions =
            TopPodcastsFragmentDirections.viewPodcastDetails(
                podcastId
            )
        val extras = FragmentNavigatorExtras(
            podcast_image to "podcastImage_$podcastId"
        )

        Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)
            .navigate(directions, extras)
    } 

这就是我绑定它的方式:

bind() from provider { PodcastDetailViewModelFactory(instance(), instance()) }

我不确定如何在 ViewModelFactory 构造函数中绑定该字符串参数,或者如何在那里传递数据,因此非常感谢任何帮助。

4

4 回答 4

2

您可以使用工厂进行绑定:

bind() from factory { podcastId: String -> 
    PodcastDetailViewModelFactory(podcastId, instance()) 
}

在现场调用它:

private val viewModelFactory: PodcastDetailViewModelFactory by instance(arg = args.podcastId) 

希望这可以帮助。

于 2020-04-08T08:28:06.000 回答
0

尝试这个 :

private val viewModelFactory: PodcastDetailViewModelFactory by instance {arg = args.podcastId}

由 Lazy 实例化,因为navArgs()是 android.app.Activity.navArgs 和 androidx.fragment.app.Fragment.navArgs 使用的 Lazy 的实现。

于 2021-10-01T14:18:36.373 回答
0

我通过切换到工厂绑定来解决这个问题,就像 romainbsl 建议的那样,但是片段中的调用有点不同。

绑定变成:

bind() from factory { podcastId: String -> 
    PodcastDetailViewModelFactory(podcastId, instance()) 
}

现场电话变成了:

private val viewModelFactory: PodcastDetailViewModelFactory by instance(arg = args.podcastId)
于 2020-04-08T20:13:36.957 回答
0

尝试这个

private val viewModel by viewModels<PodcastDetailViewModel> {
  val viewModelFactory: PodcastDetailViewModelFactory by instance(arg = args.podcastId)
  viewModelFactory
}

或者

private val viewModel by activityViewModels<PodcastDetailViewModel> {
  val viewModelFactory: PodcastDetailViewModelFactory by instance(arg = args.podcastId)
  viewModelFactory
}
于 2021-07-16T17:49:18.447 回答