问题 跨多个进程的Otto / EventBus


是否有可能 post 一个过程中的事件(例如内部 SyncAdapter 其中有 android:process=":sync" 清单属性)并在另一个(在常规应用程序UI中)接收它 玫瑰油 要么 EventBus

我知道 Intent 和 BroadcastReceiver 工作得很好,可以跨多个流程进行通信,但我希望Otto / EventBus具有简单性和灵活性。


12029
2017-08-29 12:20


起源



答案:


不,这是不可能的,如Otto,greenrobot的EventBus,和 LocalBroadcastManager 都是进程内解决方案。

您可以考虑简单地删除 android:process 清单中的属性,因此它都在一个进程中运行。


13
2017-08-29 12:25



但后来我输了 sync 应用程序关闭时的功能(因为 :sync 过程是常见的共享过程并且正在后台工作)? “属性android:exported =”true“允许您的应用程序(包括系统)以外的进程访问服务。属性android:process =”:sync“告诉系统在名为sync的全局共享进程中运行服务“。 - developer.android.com/training/sync-adapters/... - svenkapudija
@svenkapudija:你不需要使用 android:process=":sync" 用一个 SyncAdapter。 “因为:同步过程是常见的共享过程,并且正在后台工作” - 在您使用的几个组件之间会很常见 android:process=":sync"。 它与设备上的任何其他东西都不相同。 - CommonsWare
还认为:Sync需要SyncAdapter才能在后台运行。事实证明并非如此,通过删除它你可以在后台同步,同时让你的UI知道(通过奥托或广播)发生的事情 - Entreco
@CommonsWare是否有任何解决方案可以在BroadcastReceiver之外的两个不同进程之间进行通信?我正在使用前台服务(由于平台错误,它必须在不同的进程中运行。)并且希望与活动进行通信。 - VishalKale
@VishalKale:让活动绑定到服务并提供AIDL定义的回调。或者,让活动发送一个 PendingIntent, ResultReceiver, 要么 Messenger 作为额外的服务 startService()  Intent。或者,有服务的过程也有 ContentProvider 活动使用的。 - CommonsWare


答案:


不,这是不可能的,如Otto,greenrobot的EventBus,和 LocalBroadcastManager 都是进程内解决方案。

您可以考虑简单地删除 android:process 清单中的属性,因此它都在一个进程中运行。


13
2017-08-29 12:25



但后来我输了 sync 应用程序关闭时的功能(因为 :sync 过程是常见的共享过程并且正在后台工作)? “属性android:exported =”true“允许您的应用程序(包括系统)以外的进程访问服务。属性android:process =”:sync“告诉系统在名为sync的全局共享进程中运行服务“。 - developer.android.com/training/sync-adapters/... - svenkapudija
@svenkapudija:你不需要使用 android:process=":sync" 用一个 SyncAdapter。 “因为:同步过程是常见的共享过程,并且正在后台工作” - 在您使用的几个组件之间会很常见 android:process=":sync"。 它与设备上的任何其他东西都不相同。 - CommonsWare
还认为:Sync需要SyncAdapter才能在后台运行。事实证明并非如此,通过删除它你可以在后台同步,同时让你的UI知道(通过奥托或广播)发生的事情 - Entreco
@CommonsWare是否有任何解决方案可以在BroadcastReceiver之外的两个不同进程之间进行通信?我正在使用前台服务(由于平台错误,它必须在不同的进程中运行。)并且希望与活动进行通信。 - VishalKale
@VishalKale:让活动绑定到服务并提供AIDL定义的回调。或者,让活动发送一个 PendingIntent, ResultReceiver, 要么 Messenger 作为额外的服务 startService()  Intent。或者,有服务的过程也有 ContentProvider 活动使用的。 - CommonsWare


我知道这个问题有点陈旧,但似乎有一个库声称它可以处理与事件总线/ Rx样式架构的跨进程通信。

https://github.com/edisonw/PennStation

免责声明:我没有尝试过这个,只是发现了它,它声称做了这个问题的问题。


1
2017-07-06 18:32





我知道答案已被接受,但我想我会写一些关于我是如何解决这个问题的,如果有人遇到这个问题并且很好奇代码的样子。

如果你正在使用Otto,我按照上面接受的答案删除了 android:process 从清单。我也按照这里提供的答案 如何使用Otto事件总线将事件从Service发送到Activity?,因为没有在主线程上运行而抛出了一个Bus异常。因此,我将两个答案组合在一起,并根据上面的链接在主线程上创建了一个总线。

public class MainThreadBus extends Bus {
    private final Handler mHandler = new Handler(Looper.getMainLooper());
    @Override
    public void post(final Object event) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            super.post(event);
        } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    MainThreadBus.super.post(event);
                }
            });
        }
    }
}

然后我创建了一个可以在应用程序中的任何位置使用的Bus单例:

public final class BusProvider {
    private static final MainThreadBus BUS = new MainThreadBus();

    public static MainThreadBus getInstance() {
        return BUS;
    }

    private BusProvider() {
    }
}

在我的SyncAdapter中,我使用以下代码启动事件, BusProvider.getInstance().post(event); 在我的应用程序片段中,我只是订阅了该事件。

当应用程序处于前台以及在应用程序被刷掉后在后台启动同步适配器时,这非常正常。


0
2017-07-24 02:55





没有, 但你可以使用过境。例如使用 BroadcastReceiver:在一个过程中,发送一个 broadcast 与您的数据,然后通过内部 BroadcastReceiver  onReceive  方法,发布otto事件。

像我的代码:

public class ReceiveMessageBroadcastReceiver extends BroadcastReceiver {

    public static final String ACTION_RECEIVE_MESSAGE
            = "me.drakeet.xxxxxx.ACTION_RECEIVE_MESSAGE";
    public static final String AGR_MESSAGE = "AGR_MESSAGE";


    // this method can be called in other processes
    public static void sendBroadcast(Context context, MessageContent content) {
        Intent intent = new Intent();
        intent.setAction(ACTION_RECEIVE_MESSAGE);
        intent.putExtra(AGR_MESSAGE, content);
        context.sendBroadcast(intent);
    }


    // this method will run in your default process, so you can post otto events to your
    // default process
    @Override public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(ACTION_RECEIVE_MESSAGE)) {
            MessageContent content = intent.getParcelableExtra(AGR_MESSAGE);
            Otto.getSeat().post(new PlayMessageReceivedEvent(content));
        }
    }
}

0
2017-12-17 14:18