You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通知Fragment:MainActivity中mMonthlySubscribed变量状态已变更?

针对你的场景,我给你整理了几个实用的方案,从Google推荐的最佳实践到传统的实现方式都有,你可以根据项目情况选择:

方案一:使用ViewModel + LiveData(最推荐,生命周期安全)

这是Android Jetpack的标准解决方案,能完美解决Activity与Fragment之间的通信问题,不仅生命周期安全,还能自动处理配置变化(比如屏幕旋转)时的数据保留,同时实现代码解耦。

步骤说明:

  1. 创建一个共享的ViewModel,用来存储订阅状态并通过LiveData发送变更通知;
  2. 在MainActivity中更新ViewModel的状态;
  3. 在两个Fragment中观察ViewModel的LiveData,响应状态变化。

代码示例:

1. 定义共享ViewModel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.MutableLiveData

class SubscriptionViewModel : ViewModel() {
    // 内部可变的LiveData,仅让Activity修改状态
    private val _isMonthlySubscribed = MutableLiveData<Boolean>()
    // 对外暴露不可变的LiveData,Fragment只能观察
    val isMonthlySubscribed = _isMonthlySubscribed

    // 更新订阅状态的方法
    fun updateSubscriptionStatus(isSubscribed: Boolean) {
        _isMonthlySubscribed.value = isSubscribed
    }
}

2. MainActivity中处理状态更新

class MainActivity : AppCompatActivity() {
    private lateinit var subscriptionViewModel: SubscriptionViewModel
    private var mMonthlySubscribed: Boolean = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 获取与Fragment共享的ViewModel实例
        subscriptionViewModel = ViewModelProvider(this)[SubscriptionViewModel::class.java]
    }

    override fun onPurchasesUpdated(result: BillingResult, purchases: MutableList<Purchase>?) {
        // 根据购买结果更新本地变量
        mMonthlySubscribed = /* 这里根据实际购买逻辑判断是否订阅 */
        
        // 通知ViewModel更新状态,自动同步到所有观察者
        subscriptionViewModel.updateSubscriptionStatus(mMonthlySubscribed)
        
        // 如果你仍需要直接导航到对应Fragment,可以保留这行,但更推荐让Fragment自主响应变化
        // loadFragment(if (mMonthlySubscribed) FragmentSubscribed() else FragmentUnsubscribed())
    }

    // 你的Fragment导航方法
    private fun loadFragment(fragment: Fragment) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, fragment)
            .commit()
    }
}

3. Fragment中观察状态变化

FragmentSubscribed:

class FragmentSubscribed : Fragment() {
    private lateinit var subscriptionViewModel: SubscriptionViewModel

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // 获取与Activity共享的ViewModel
        subscriptionViewModel = ViewModelProvider(requireActivity())[SubscriptionViewModel::class.java]
        
        // 观察订阅状态变化
        subscriptionViewModel.isMonthlySubscribed.observe(viewLifecycleOwner) { isSubscribed ->
            if (!isSubscribed) {
                // 状态变为未订阅,通知Activity导航到对应的Fragment
                (activity as MainActivity).loadFragment(FragmentUnsubscribed())
                // 也可以直接更新当前Fragment的UI,比如显示未订阅提示
            }
        }
    }
}

FragmentUnsubscribed:

class FragmentUnsubscribed : Fragment() {
    private lateinit var subscriptionViewModel: SubscriptionViewModel

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        subscriptionViewModel = ViewModelProvider(requireActivity())[SubscriptionViewModel::class.java]
        
        subscriptionViewModel.isMonthlySubscribed.observe(viewLifecycleOwner) { isSubscribed ->
            if (isSubscribed) {
                (activity as MainActivity).loadFragment(FragmentSubscribed())
                // 或者更新UI,比如显示已订阅专属内容
            }
        }
    }
}

方案二:使用接口回调(传统实现)

如果你的项目还没有引入Jetpack组件,这种传统的接口回调方式也能解决问题,需要注意的是要在Fragment销毁时取消注册,避免内存泄漏。

步骤说明:

  1. 定义一个状态变更的回调接口;
  2. 让Fragment实现该接口,并在依附Activity时注册;
  3. MainActivity在状态变化时调用接口方法通知Fragment。

代码示例:

1. 定义回调接口

interface SubscriptionStatusListener {
    fun onSubscriptionStatusChanged(isSubscribed: Boolean)
}

2. MainActivity中维护监听器

class MainActivity : AppCompatActivity() {
    private var mMonthlySubscribed: Boolean = false
    private var subscriptionListener: SubscriptionStatusListener? = null

    // 注册监听器
    fun setSubscriptionListener(listener: SubscriptionStatusListener) {
        this.subscriptionListener = listener
    }

    // 取消注册,防止内存泄漏
    fun removeSubscriptionListener() {
        this.subscriptionListener = null
    }

    override fun onPurchasesUpdated(result: BillingResult, purchases: MutableList<Purchase>?) {
        mMonthlySubscribed = /* 根据购买结果判断 */
        // 通知所有注册的Fragment
        subscriptionListener?.onSubscriptionStatusChanged(mMonthlySubscribed)
        
        // 可选:保留直接导航逻辑
        // loadFragment(if (mMonthlySubscribed) FragmentSubscribed() else FragmentUnsubscribed())
    }

    // 你的loadFragment方法...
}

3. Fragment实现接口

FragmentSubscribed:

class FragmentSubscribed : Fragment(), SubscriptionStatusListener {
    override fun onAttach(context: Context) {
        super.onAttach(context)
        // 依附Activity时注册监听器
        if (context is MainActivity) {
            context.setSubscriptionListener(this)
        }
    }

    override fun onDetach() {
        super.onDetach()
        // 销毁时取消注册,避免内存泄漏
        (activity as MainActivity).removeSubscriptionListener()
    }

    override fun onSubscriptionStatusChanged(isSubscribed: Boolean) {
        if (!isSubscribed) {
            (activity as MainActivity).loadFragment(FragmentUnsubscribed())
        }
    }
}

FragmentUnsubscribed:

class FragmentUnsubscribed : Fragment(), SubscriptionStatusListener {
    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is MainActivity) {
            context.setSubscriptionListener(this)
        }
    }

    override fun onDetach() {
        super.onDetach()
        (activity as MainActivity).removeSubscriptionListener()
    }

    override fun onSubscriptionStatusChanged(isSubscribed: Boolean) {
        if (isSubscribed) {
            (activity as MainActivity).loadFragment(FragmentSubscribed())
        }
    }
}

方案三:EventBus(不推荐,仅作补充)

如果你的项目已经在使用EventBus(比如GreenRobot EventBus),可以通过发送事件的方式通知Fragment,但这种方式会增加代码耦合度,调试难度也更高,所以不推荐作为首选方案。

简单示例:

  1. 定义订阅状态变更事件:
class SubscriptionStatusEvent(val isSubscribed: Boolean)
  1. MainActivity发送事件:
EventBus.getDefault().post(SubscriptionStatusEvent(mMonthlySubscribed))
  1. Fragment注册并接收事件:
@Subscribe(threadMode = ThreadMode.MAIN)
fun onSubscriptionStatusChanged(event: SubscriptionStatusEvent) {
    // 处理状态变化
}

override fun onStart() {
    super.onStart()
    EventBus.getDefault().register(this)
}

override fun onStop() {
    super.onStop()
    EventBus.getDefault().unregister(this)
}

总结

优先推荐ViewModel + LiveData方案,它是Google官方推崇的架构模式,能解决大部分组件通信问题,同时保证代码的可维护性和稳定性。如果是老项目,接口回调也是可靠的选择,但要注意内存泄漏问题。

内容的提问来源于stack exchange,提问作者channae

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:05:32