Исключение во время выполнения Otto

Мое приложение использует Otto повсюду, но я постоянно сталкиваюсь с одним и тем же сбоем Runtime Exception. Это происходит с несколькими разными событиями, и это заставляет меня думать, что я неправильно реализую otto. Я использую технику Main Thread Bus следующим образом:

/**
 * Otto bus that enforces bus messages posted on the main thread
 * Adapted from: http://stackoverflow.com/questions/15431768/how-to-send-event-from-service-to-activity-with-otto-event-bus
 */
public class MXRMainThreadBus extends Bus {
    private final Bus mBus;
    private final Handler mHandler = new Handler(Looper.getMainLooper());

    public MXRMainThreadBus(final Bus bus) {
        if (bus == null) {
            throw new NullPointerException("bus must not be null");
        }
        mBus = bus;
    }

    @Override public void register(Object obj) {
        mBus.register(obj);
    }

    @Override public void unregister(Object obj) {
        mBus.unregister(obj);
    }

    @Override public void post(final Object event) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            mBus.post(event);
        } else {
            mHandler.post(new Runnable() {
                @Override public void run() {
                    mBus.post(event);
                }
            });
        }
    }
}

Вот мой провайдер автобусов:

/**
 * Otto Bus Provider singleton
 */
public class BusProvider {
    private static MXRMainThreadBus BUS;

    private BusProvider() {}

    public static Bus getInstance() {
        if(BUS == null) {
            BUS = new MXRMainThreadBus(new Bus());
        }
        return BUS;
    }
}

Вот трассировка стека (самая распространенная):

java.lang.RuntimeException
com.squareup.otto.Bus.throwRuntimeException(Bus.java:444)
com.squareup.otto.Bus.dispatch(Bus.java:374)
com.squareup.otto.Bus.dispatchQueuedEvents(Bus.java:355)
com.squareup.otto.Bus.post(Bus.java:324)
com.myxer.android.unicorn.utils.MXRMainThreadBus.post(MXRMainThreadBus.java:33)
com.myxer.android.unicorn.api.MXRApiController$1.onResponse(MXRApiController.java:173)
com.myxer.android.unicorn.api.MXRApiController$1.onResponse(MXRApiController.java:170)
com.myxer.android.unicorn.volley.GsonRequest.deliverResponse(GsonRequest.java:117)
com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
android.os.Handler.handleCallback(Handler.java:725)
android.os.Handler.dispatchMessage(Handler.java:92)
android.os.Looper.loop(Looper.java:137)
android.app.ActivityThread.main(ActivityThread.java:5185)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:511)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:564)
dalvik.system.NativeStart.main(Native Method)
Caused by: com.myxer.android.unicorn.fragments.MXRStationGridFragment.onStationReceivedImpl(MXRStationGridFragment.java:142)
com.myxer.android.unicorn.fragments.tabhosted.MXRRelatedStationsGridFragment.onStationReceived(MXRRelatedStationsGridFragment.java:75)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:511)
com.squareup.otto.EventHandler.handleEvent(EventHandler.java:89)
com.squareup.otto.Bus.dispatch(Bus.java:372)
com.squareup.otto.Bus.dispatchQueuedEvents(Bus.java:355)
com.squareup.otto.Bus.post(Bus.java:324)
com.myxer.android.unicorn.utils.MXRMainThreadBus.post(MXRMainThreadBus.java:33)
com.myxer.android.unicorn.api.MXRApiController$1.onResponse(MXRApiController.java:173)
com.myxer.android.unicorn.api.MXRApiController$1.onResponse(MXRApiController.java:170)
com.myxer.android.unicorn.volley.GsonRequest.deliverResponse(GsonRequest.java:117)
com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
android.os.Handler.handleCallback(Handler.java:725)
android.os.Handler.dispatchMessage(Handler.java:92)
android.os.Looper.loop(Looper.java:137)
android.app.ActivityThread.main(ActivityThread.java:5185)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:511)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:797)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:564)
dalvik.system.NativeStart.main(Native Method)

person SamIAmHarris    schedule 12.05.2014    source источник
comment
Это не полная трассировка стека. Вероятно, вы ловите исключение в своей среде IDE. Запустите точку исключения, затем проверьте LogCat, чтобы увидеть полную трассировку стека, включая само сообщение об ошибке.   -  person CommonsWare    schedule 13.05.2014
comment
Я предполагаю, что это проблема параллелизма, с которой вы столкнулись. Похоже, вы можете зарегистрироваться/отменить регистрацию в любом потоке, но публикация происходит только в основном потоке. Если это предположение верно, то обертывание подписки/отписки аналогично событию публикации должно помочь.   -  person sergej shafarenka    schedule 14.06.2014


Ответы (1)


Если вы запустите Bus в другом потоке, а не в основном потоке, вы столкнетесь с этим исключением. Поставщик Otto Bus работает в основном потоке. Однако существует оболочка, которая позволяет передавать события другим потокам, кроме основного. Это можно использовать для служб, когда вы пытаетесь передать сообщения из работающей фоновой службы в поток пользовательского интерфейса. Вот обертка:

public class MainThreadBus extends Bus
  {
    private final Bus     mBus;
    private final Handler mHandler = new Handler(Looper.getMainLooper());

    public MainThreadBus(final Bus bus)
      {
        if (bus == null)
          {
            throw new NullPointerException("bus must not be null");
          }
        mBus = bus;
      }

    @Override
    public void register(Object obj)
      {
        mBus.register(obj);
      }

    @Override
    public void unregister(Object obj)
      {
        mBus.unregister(obj);
      }

    @Override
    public void post(final Object event)
      {
        if (Looper.myLooper() == Looper.getMainLooper())
          {
            mBus.post(event);
          }
        else
          {
            mHandler.post(new Runnable()
              {
                @Override
                public void run()
                  {
                    mBus.post(event);
                  }
              });
          }
      }
  }
person greenspand    schedule 04.09.2014