使用Fragment Navigation跳转时如何获取目标Fragment实例并调用方法
解决方案
你原来通过获取目标Fragment实例设置回调的思路不适合Navigation组件的使用场景,Navigation负责Fragment的创建和生命周期管理,官方提供了更稳定的跨Fragment数据传递方案,以下是可直接落地的实现方式:
方案1:使用Fragment Result API(官方推荐,适配当前场景)
AndroidX Fragment 1.3.0及以上版本提供的原生API,无需持有Fragment实例,也无需定义额外接口,适配单次数据回传场景。
步骤1:在HomeFragment中注册结果监听
在HomeFragment的onViewCreated方法中注册搜索结果监听,代码如下:
// 注册监听,requestKey需和SearchFragment中设置的保持一致 setFragmentResultListener("search_request_key") { requestKey, bundle -> // 取出搜索关键词,key自行定义即可 val searchKeyword = bundle.getString("search_keyword", "") // 执行你的搜索逻辑 doSearch(searchKeyword) }
Java版本实现:
getParentFragmentManager().setFragmentResultListener("search_request_key", getViewLifecycleOwner(), (requestKey, result) -> { String searchKeyword = result.getString("search_keyword", ""); doSearch(searchKeyword); });
步骤2:在SearchFragment中回传搜索结果
用户确认搜索后,将结果存入Bundle并回传,之后返回HomeFragment即可:
// 构造结果Bundle val resultBundle = Bundle().apply { putString("search_keyword", userInputEditText.text.toString()) } // 设置返回结果 setFragmentResult("search_request_key", resultBundle) // 返回上一级页面(HomeFragment) findNavController().popBackStack()
Java版本实现:
Bundle resultBundle = new Bundle(); resultBundle.putString("search_keyword", userInputEditText.getText().toString()); getParentFragmentManager().setFragmentResult("search_request_key", resultBundle); findNavController().popBackStack();
方案2:共享ViewModel(适合多交互、复杂数据传递场景)
如果两个Fragment之间存在多轮数据交互,可以使用作用域为宿主Activity/当前导航图的共享ViewModel实现数据共享,无需关心Fragment实例获取。
步骤1:定义共享ViewModel
class SearchViewModel : ViewModel() { // 搜索关键词LiveData val searchKeyword = MutableLiveData<String>() }
步骤2:HomeFragment中观察数据变化
在HomeFragment中获取Activity作用域的ViewModel,监听搜索关键词变化:
// 注意ViewModelProvider的参数是宿主Activity,保证两个Fragment拿到的是同一个实例 val searchViewModel = ViewModelProvider(requireActivity())[SearchViewModel::class.java] searchViewModel.searchKeyword.observe(viewLifecycleOwner) { keyword -> if (!keyword.isNullOrEmpty()) { // 执行搜索逻辑 doSearch(keyword) // 可选:消费后清空数据,避免回到页面重复触发 searchViewModel.searchKeyword.value = "" } }
步骤3:SearchFragment中更新数据
用户确认搜索时,给ViewModel的LiveData赋值:
val searchViewModel = ViewModelProvider(requireActivity())[SearchViewModel::class.java] searchViewModel.searchKeyword.value = userInputEditText.text.toString() // 返回HomeFragment findNavController().popBackStack()
不推荐方案:手动获取SearchFragment实例
如果确实需要获取实例(非常不推荐,容易因生命周期变化产生空指针、内存泄漏问题),可以通过监听导航目的地变化获取:
findNavController().addOnDestinationChangedListener { controller, destination, arguments -> if (destination.id == R.id.search_fragment) { // 从NavHostFragment的子FragmentManager中获取当前可见的Fragment实例 val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_id) as NavHostFragment val searchFragment = navHostFragment.childFragmentManager.fragments.lastOrNull() as? SearchFragment searchFragment?.addListener(yourListenerInstance) } }
该方案依赖Navigation内部实现逻辑,不同版本库可能存在兼容问题,优先选择前两种官方推荐方案。
内容的提问来源于stack exchange,提问作者Waqas Younis
相关产品推荐
相关产品推荐

