14

是否可以使用OttoEventBuspost在一个进程中发生事件(例如,在SyncAdapter其中具有android:process=":sync"manifest 属性)并在另一个进程(在常规应用程序 UI 中)接收它?

我知道这一点,Intent并且BroadcastReceiver可以很好地跨多个进程进行通信,但我希望 Otto/EventBus 具有简单性和灵活性。

4

4 回答 4

15

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

您可能会考虑简单地android:process从清单中删除该属性,以便它在一个进程中运行。

于 2014-08-29T12:25:19.310 回答
1

不,但您可以使用中转。例如使用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));
        }
    }
}
于 2015-12-17T14:18:28.253 回答
1

我知道这个问题有点老了,但似乎有一个库声称它可以处理具有事件总线/Rx 风格架构的跨进程通信。

https://github.com/edisonw/PennStation

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

于 2016-07-06T18:32:51.377 回答
0

我知道答案已经被接受,但我想我会写下我是如何解决问题的,以防有人遇到这个问题并且很好奇代码的外观。

如果您使用的是 Otto,我会按照上面接受的答案android:process从清单中删除 。我还按照此处提供的答案如何使用 Otto 事件总线将事件从服务发送到活动?,因为没有在主线程上运行而引发了总线异常。因此,我结合了这两个答案,并根据上面的链接创建了一个要在主线程上执行的总线。

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);在我的应用程序片段中,我只是订阅了该事件。

当应用程序在前台时以及在应用程序被刷掉后在后台启动同步适配器时,这工作得非常好。

于 2015-07-24T02:55:39.813 回答