如何将Fragment 2的数据传递至Activity而非Fragment 1?
问题描述
页面跳转路径:
Activity -> Fragment 1 -> Fragment 2
需要将Fragment 2的数据传递至Activity。已创建PassDataInterface并在Fragment 2的构造方法中传入,但Fragment 1作为调用Fragment 2的发起方实现了该接口,导致Activity实现的接口方法从未被调用。
代码文件
MainActivity.kt
class MainActivity : AppCompatActivity(), PassDataInterface { private val name = "Sagar" private lateinit var fragmentView: FragmentContainerView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) fragmentView = findViewById(R.id.fragmentView) val bundle = Bundle() bundle.putString("name",name) val fragment = BlankFragment() fragment.arguments = bundle supportFragmentManager.beginTransaction().add(R.id.fragmentView, fragment).commit() } override fun onPassData(title: String) { println("Activity") setTitle(title) } }
BlankFragment.kt(Fragment 1)
class BlankFragment : Fragment(),PassDataInterface { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment val view = inflater.inflate(R.layout.fragment_blank, container, false) val tv = view.findViewById<TextView>(R.id.tv) val btn = view.findViewById<Button>(R.id.btn) val name: String = arguments?.getString("name") as String btn.setOnClickListener { val bundle = Bundle() bundle.putString("name",name) val fragment2 = BlankFragment2(this) fragment2.arguments = bundle activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.fragmentView,fragment2)?.addToBackStack(null)?.commit() } tv.setText(name) return view } override fun onPassData(title: String) { println("Fragment 1") } }
BlankFragment2.kt(Fragment 2)
class BlankFragment2(val passDataInterface: PassDataInterface): Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup ? , savedInstanceState : Bundle ? ): View ? { // Inflate the layout for this fragment passDataInterface.onPassData("Fragment 2") val view = inflater.inflate(R.layout.fragment_blank2, container, false) val text = arguments ? .getString("name") as String val b2 = view.findViewById < TextView > (R.id.b2) val btnDownload = view.findViewById < Button > (R.id.btnDownload) if (checkSelfPermission(requireContext(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE), 1) } b2.text = text return view } }
当前输出
Fragment 1
期望输出
Activity
解决方案
方法一:直接传递Activity的接口实例给Fragment 2
在BlankFragment创建Fragment2时,不要传入自身的接口实现,而是传入Activity的实例(因为Activity已经实现了PassDataInterface):
修改BlankFragment中的点击事件代码:
btn.setOnClickListener { val bundle = Bundle() bundle.putString("name",name) // 强转Activity为PassDataInterface并传入Fragment2 val fragment2 = BlankFragment2(activity as PassDataInterface) fragment2.arguments = bundle activity?.supportFragmentManager?.beginTransaction()?.replace(R.id.fragmentView,fragment2)?.addToBackStack(null)?.commit() }
修改后,Fragment2调用passDataInterface.onPassData()时,会直接触发Activity的实现方法,输出"Activity"。
方法二:让Fragment1转发数据到Activity
保留当前Fragment2传入Fragment1的逻辑,修改Fragment1的onPassData方法,将数据转发给Activity:
修改BlankFragment的onPassData方法:
override fun onPassData(title: String) { // 调用Activity的接口方法完成转发 (activity as PassDataInterface).onPassData(title) }
这样Fragment2调用Fragment1的接口方法后,Fragment1会把数据传递给Activity,最终输出"Activity"。
方法三:使用ViewModel(推荐的组件化方案)
跨Fragment和Activity传递数据时,ViewModel是更健壮的选择,无需依赖接口传递,避免强转和生命周期问题:
- 创建共享ViewModel:
class SharedViewModel : ViewModel() { val dataLiveData = MutableLiveData<String>() }
- 在MainActivity中观察LiveData:
class MainActivity : AppCompatActivity() { private val sharedViewModel: SharedViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // ... 原有初始化代码 sharedViewModel.dataLiveData.observe(this) { title -> println("Activity") setTitle(title) } } }
- 在BlankFragment2中获取ViewModel并发送数据:
class BlankFragment2 : Fragment() { private val sharedViewModel: SharedViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // 发送数据到ViewModel sharedViewModel.dataLiveData.postValue("Fragment 2") // ... 原有视图初始化代码 val view = inflater.inflate(R.layout.fragment_blank2, container, false) // ... 后续代码 return view } }
这种方式无需定义PassDataInterface,利用Jetpack组件的生命周期感知能力,更符合Android架构规范。
内容的提问来源于stack exchange,提问作者user20088323
相关产品推荐
相关产品推荐

