事件总线碎片注销

6

我有一个启动画面片段,已经注册到事件总线:

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}

如果屏幕自动锁定(或任何可能调用onStop的事件),则容器活动将停止,并且片段将不再能够接收(网络)事件。我正在考虑将“取消注册”逻辑移至onDestroy方法。这是个好主意吗?
2个回答

11

可以将事件总线事件移动到onStart()onStop(),但是你应该知道,在onSaveInstanceState()之后某些方法不能被调用(例如,解除DialogFragment会导致崩溃)。

因此,虽然这个例子是针对Otto的,但我已经转换为EventBus,并且我个人有一个包装器,可以在应用程序暂停时存储事件。

public enum SingletonBus {
    INSTANCE;

    private static String TAG = SingletonBus.class.getSimpleName();

    private final Vector<Object> eventQueueBuffer = new Vector<>();

    private boolean paused;

    public <T> void post(final T event) {
            if (paused) {
                eventQueueBuffer.add(event);
            } else {
                EventBus.getDefault().post(event);
            }
    }

    public <T> void register(T subscriber) {
        EventBus.getDefault().register(subscriber);
    }

    public <T> void unregister(T subscriber) {
        EventBus.getDefault().unregister(subscriber);
    }

    public boolean isPaused() {
        return paused;
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
        if (!paused) {
            Iterator<Object> eventIterator = eventQueueBuffer.iterator();
            while (eventIterator.hasNext()) {
                Object event = eventIterator.next();
                post(event);
                eventIterator.remove();
            }
        }
    }
}

接着,在一个类似 BaseActivity 的基类中,

public class BaseActivity extends AppCompatActivity {
     @Override
     public void onPostResume() {
          super.onPostResume();
          SingletonBus.INSTANCE.setPaused(false);
     }

     @Override
     public void onPause() {
          SingletonBus.INSTANCE.setPaused(true);
          super.onPause();
     }
}

1
是的,这真是个麻烦事,当我遇到它时感到很惊讶。因此,我只允许在应用程序未暂停时传输事件。 - EpicPandaForce
这是因为系统可能会在 onSaveInstanceState() 之后无情地杀死您的进程,因此您可能会丢失刚刚提交的事务。顺便说一下,代码很好,但为什么要使用 Vector - Gil Vegliach
@EpicPandaForce:我也是这么想的,无论如何,你需要更多的同步来使它线程安全,例如post()不是原子性的,暂停标志不是“内存一致”的等等。 - Gil Vegliach
1
@Gil 嗯,我还没有遇到这方面的问题,但我可能需要更好地同步它,然后......我似乎忘记了pausedvolatile标志,这是确定的。谢谢你的建议。此外,我在我的示例中意识到它只应该在onPostResume()中将paused设置为false,因此我做出了相应的更改。 - EpicPandaForce
1
没关系,是我的错;另一个活动正在拦截相同的事件。我修补了这个问题,为每个事件添加了“source = class.getSimpleName”,这样我就可以识别调用者了。 - Jumpa
显示剩余6条评论

2
我最近遇到了类似的问题。首先我使用了Otto,然后切换到了greenrobot的EventBus。使用EventBus,您可以将对象注册为“sticky”。即,在注册后,此对象将自动接收每个等待的sticky事件。这些事件必须以sticky方式发布。考虑在不需要时删除sticky事件。如果您只想接收此事件一次,则应将其删除。也许这种方法适合您的需求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接