如何通过 navArgs 将参数传递给详细 ViewModel

4
我有一个包含播客列表的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个回答

2
您可以使用工厂来绑定您的内容:
bind() from factory { podcastId: String -> 
    PodcastDetailViewModelFactory(podcastId, instance()) 
}

使用以下方式在现场调用:

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

希望这可以帮助您。

我想我可能已经解决了注入问题,但现在我遇到了一个IllegalStateException,因为“Fragment has null arguments”,我认为这是导航组件的问题,但我也无法解决它。 - Cameron

0

试一下这个:

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

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


0
我通过切换到工厂绑定来解决了这个问题,就像romainbsl建议的那样,但片段中的调用有点不同。
绑定变成了:
bind() from factory { podcastId: String -> 
    PodcastDetailViewModelFactory(podcastId, instance()) 
}

现场呼叫变成了:

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

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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接