【问题标题】:EventBus : Activity does not receive event when app is in the backgroundEventBus :当应用程序在后台时,活动不接收事件
【发布时间】:2023-03-25 02:15:02
【问题描述】:

我使用EventBusActivityService 之间进行通信。 今天我遇到了一个问题,不知道为什么。

  1. 我有ActivityFragmentService。他们都工作正常。

  2. ActivityFragmentregistered他们到ReceiveeventsService交付

  3. ActivityFragment中,当onDestroy()被调用时,我un-register他们。

  4. 在正常情况下,Services 传递eventsFragmentActivity 可以接收那些events 并正常工作。

  5. 但是当App 被推到background 上时(通过按主页或电源按钮),只有Fragment 接收从Service 传递的事件,而Activity 不接收它们。

  6. 我在onPause()ActivityFragment 中都没有做任何事情。

问题:

对此有什么解释吗?我怎样才能让我的Activity 收到像Fragment 这样的事件,当应用程序被推送到后台时?

【问题讨论】:

  • 也许活动的onDestroy 被调用并取消注册。
  • 从你的 onDestroy 方法中删除 unregister(this);,然后试试。
  • I'm using EventBus to communicate between Activity and Service 这是错误的做法,请改用“绑定本地服务”模式
  • 因为您现在遇到的问题?如果您按下主页/返回按钮,您的活动可能随时被销毁,因此它不会收到任何数据
  • 我认为完全摒弃 eventbus 作为应用程序/服务通信的选项是不公平的。这仅取决于消息的目的。如果应用程序依赖于服务的状态,那么绑定是最好的选择。如果服务引发事件,那么总线会更好。此外,粘性事件将让您的活动在再次注册后接收事件。

标签: android android-fragments service background-process event-bus


【解决方案1】:

在 EventBus 版本 3.0.0 中,您可以使用 Sticky 帖子。

通过这种方式,您可以并且应该在“onStop()”上取消注册 EventBus,以防止内存泄漏并在 App 进入前台时仍然接收事件。

以这种方式发布活动:

EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));

使用粘性标志订阅事件,如下所示:

@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {   
    textField.setText(event.message);
}

EventBus 文档: http://greenrobot.org/eventbus/documentation/configuration/sticky-events/

【讨论】:

    【解决方案2】:

    当用户按下返回/主页按钮时,Activity 可以随时销毁,因此您将无法使用 EventBus 接收数据。如果您在Activity 处于后台时尝试接收数据,它可能会泄漏内存并且应用程序将崩溃。

    当用户恢复activity 时,还有其他方法可以获取Activity 中的数据。

    您可以使用sharedpreferences 或本地数据库将传递的结果保存为service。当用户导航回活动时,从sharedpreferences 或数据库中读取它。

    这样就不会出现内存泄漏或数据丢失的问题。

    编辑 1:

    始终建议取消注册onPauseonStop 中的侦听器,因为活动不在前台时不需要这些事件。而且由于onDestroy()不能保证被调用,因此当Activity不再打开时你可以继续接收广播。

    【讨论】:

    • 我想问为什么我在Activity中收不到事件而Fragment收到了?当 Activity 被销毁时,我取消注册以接收事件,我不再需要接收事件。我的问题是为什么还没有调用 onDestroyed() 但我仍然无法接收事件。
    • 您能够接收事件的最后一个回调是什么? onPauseonStop?
    • 是的,只有在后台推送 App 时才会出现问题。但是 Fragment 效果很好
    • 好的,让我先澄清一下。您可以在调用 onStop 之前接收事件。而您,因为您正在取消注册 onDestroy 中的事件,所以您期待事件直到 onDestroy 被调用。对吗?
    • 如果activityonStop 之后被杀死但onDestroy 没有被调用怎么办。因此您无法接收事件?
    【解决方案3】:

    Activity 类提供了两个生命周期方法,onStop() 和 onRestart() 不可见时(后台模式),它们允许您专门处理您的活动如何处理停止和重新启动。与标识部分 UI 阻塞的暂停状态不同,停止状态可确保 UI 不再可见,并且用户的焦点位于单独的 Activity(或完全单独的应用程序)中。

    为了理解这个循环,看一下这张图片,它显示了当您的应用退出前台模式时的流程。

    在您的情况下,您可以像这样处理问题。

    • 为用户提供一种使用本地数据库 (Sqlite)、sharedPreferences 保存持久应用程序数据的机制。
    • 在 onStop() 方法上处理您的数据持久性。
    • 当用户回调您的应用时,您需要使用 onRestart() 方法恢复数据。

      这是实现它的方法。

      public class Calc extends Activity {
      public static final String PREFS_NAME = "MyPrefsFile";
      
      @Override
      protected void onCreate(Bundle state){
         super.onCreate(state);
         . . .
      
         // Restore preferences
         SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
         boolean silent = settings.getBoolean("silentMode", false);
         setSilent(silent);
      }
      
      @Override
      protected void onStop(){
         super.onStop();
      
        // We need an Editor object to make preference changes.
        // All objects are from android.context.Context
        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putBoolean("silentMode", mSilentMode);
      
        // Commit the edits!
        editor.commit();
      }
      

      }

    请阅读Android Developer site的以下文档

    【讨论】:

      【解决方案4】:

      很难猜出你做了什么导致这种行为,考虑提供一些代码。

      但显而易见的是你有一些设计缺陷。

      当用户从应用程序导航返回时,您必须从您的 UI 组件(如活动或片段)中取消注册任何事件总线或侦听器,如果您不这样做,则很有可能泄露您的活动及其所有资源持有。

      您应该将您在后台服务中接收或计算的任何数据存储到文件或数据库中,当用户打开或重新打开您的应用时,您应该检查该数据并对其采取行动。

      【讨论】:

        【解决方案5】:

        需要更多代码或示例来适当地帮助您。但请尝试以下方法。

        1. 您的活动是从 baseActivity 扩展而来的吗?如果是这样,请删除 onDestroy 事件总线注销代码并检查。
        2. 在开发者选项中,检查不保留活动选项是否未选中。
        3. 除非您覆盖了 back 事件,否则无论如何按回都会杀死您的应用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-13
          • 1970-01-01
          • 1970-01-01
          • 2015-04-27
          相关资源
          最近更新 更多