Kotlin中如何实现Fragment向Activity传输数据并修改变量
从Fragment修改MainActivity内部变量的实现方案
下面是几种生产环境常用的实现方式,按推荐优先级排序:
方案1:使用共享ViewModel(官方推荐,生命周期安全)
这是Jetpack组件提供的规范实现,不会有内存泄漏问题,也能保证屏幕旋转等场景下数据不丢失。
- 首先定义Activity和Fragment共享的ViewModel类
class SharedViewModel : ViewModel() { // 你要修改的目标变量,用MutableLiveData包裹支持观察 val targetParam = MutableLiveData<String>() }
- 在MainActivity中初始化ViewModel,观察变量变化
class MainActivity : AppCompatActivity() { // 你自己在Activity内部定义的、需要被修改的变量 private var localVariable: String = "" private lateinit var sharedViewModel: SharedViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 初始化当前Activity作用域的ViewModel sharedViewModel = ViewModelProvider(this)[SharedViewModel::class.java] // 观察变量变化,收到新值时更新本地变量 sharedViewModel.targetParam.observe(this) { newVal -> localVariable = newVal // 变量更新后你要做的其他逻辑可以写在这里 } } }
- 在Fragment中获取同一个ViewModel实例,需要修改变量时直接更新值即可
class DemoFragment : Fragment() { private lateinit var sharedViewModel: SharedViewModel override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 注意这里传入requireActivity(),获取的是和宿主Activity绑定的同一个ViewModel实例 sharedViewModel = ViewModelProvider(requireActivity())[SharedViewModel::class.java] // 比如点击按钮时修改Activity的变量 binding.updateBtn.setOnClickListener { // 主线程用setValue,子线程用postValue sharedViewModel.targetParam.value = "Fragment传过来的新值" } } }
方案2:接口回调(适合小项目,不引入Jetpack组件的场景)
通过接口解耦Fragment和Activity的直接依赖,避免强转崩溃问题。
- 在Fragment中定义回调接口,在附着到宿主时绑定监听
class DemoFragment : Fragment() { // 定义变量修改的回调接口 interface VariableUpdateListener { fun onUpdate(newValue: String) } private var updateListener: VariableUpdateListener? = null override fun onAttach(context: Context) { super.onAttach(context) // 校验宿主Activity是否实现了对应接口 updateListener = context as? VariableUpdateListener ?: throw IllegalStateException("宿主Activity必须实现VariableUpdateListener接口") } // 需要修改变量时调用回调方法 private fun changeActivityVar() { updateListener?.onUpdate("Fragment传的新值") } override fun onDetach() { super.onDetach() // 置空引用避免内存泄漏 updateListener = null } }
- 让MainActivity实现该接口,在重写方法中修改自身变量
class MainActivity : AppCompatActivity(), DemoFragment.VariableUpdateListener { private var localVariable: String = "" override fun onUpdate(newValue: String) { // 直接给本地变量赋值 localVariable = newValue } }
不推荐的写法
不要直接在Fragment中将requireActivity()强转为MainActivity类型,直接访问/修改Activity的公开变量。这种写法耦合度极高,Fragment一旦被其他Activity复用就会抛出类型转换异常,处理不好还会引发内存泄漏。
注意:所有跨组件修改变量的场景,都要保证引用的生命周期安全,不要长期持有宿主的强引用。
内容的提问来源于stack exchange,提问作者Nacimooo
相关产品推荐
相关产品推荐

