是否可以仅通过Android中的单个top activity来处理Event Bus的事件?
Is it possible to process Event Bus's events only by a single top activity in Android?
当我们使用事件总线(来自 Guava)从服务器获取异步响应时 - 一切正常。但是,如果我们想在顶部打开相同 activity 的另一个实例,那么我们的订阅事件也将在底部处理(已停止)activity 导致不同来源的错误。
是否可以使事件总线的事件仅由当前顶部的单个订阅者处理activity?
有两种解决方法:
- 您订阅的地点和订阅前的活动请先取消订阅,然后再订阅。之后将在 eventbus 事件堆栈中一次只执行一个订阅。
- 我认为您有一个 BaseActivity,每当您创建一个时,事件总线订阅就会在每个 activity 上发生。为此,您可以在onresume中订阅,在onpause中取消订阅将解决您的问题。
当你在 activity re-creates 之前使用以下方法删除所有粘性事件:-
stickyEvent= EventBus.getDefault().getStickyEvent(classType);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
}
对于那些曾经利用事件总线范式来获取异步操作结果的人(并保持 activity 或片段的方向更改事件和正确的工作,即使我们当前打开了多个相同的活动),我建议以下样板实现。它基于Greenrobot的事件总线库,当然在这里使用任何其他库也不难。
首先,让我们创建一种助手class来为事件总线发送事件:
/**
* Helps to send sticky events avoiding them to be sent when the current screen (content entity)
* is about to be closed.
*/
public enum EventBusHelper {
/** Single instance. */
INSTANCE;
/**
* Posts sticky event to make activity fetch it (if activity is not finishing).
*
* @param activity An activity to check state.
* @param event An event to be fired.
* */
public void postStickyIfNotFinishing(@NonNull Activity activity, Object event) {
postStickyIfNotFinishing(activity.isFinishing(), event);
}
/**
* Posts sticky event to make fragment fetch it (if fragment is not finishing).
*
* @param fragment A fragment to check state.
* @param event An event to be fired.
* */
public void postStickyIfNotFinishing(@NonNull Fragment fragment, Object event) {
postStickyIfNotFinishing(fragment.isRemoving(), event);
}
/**
* Posts sticky event if a subscriber is not going to be finished.
*
* @param isFinishing True - if subscriber will be finished.
* @param event An event to be sent.
* */
private void postStickyIfNotFinishing(boolean isFinishing, Object event) {
if (!isFinishing)
EventBus.getDefault().postSticky(event);
}
此 class 的主要目的是仅当我们的 activity、片段(对话片段)不会关闭时才发送 Subscribe-methods 的事件。否则,当我们在 activity(片段等)的下一次启动时获取一些即时数据而没有首先触发我们的请求时,我们将得到不可接受的行为。但是当我们的屏幕实体(activity,片段)在屏幕方向改变后即将被重新创建时,这种事件发送方法不会阻止事件的发送。
下一步 - 是在我们的 activity 或片段:
的启动和停止操作上注册和注销事件总线
/**
* Initializing event bus to process completed tasks.
* */
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
/**
* Stopping event bus to avoid background ops processing.
* */
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
有两个必要:
- 为了避免任何后台操作,当我们收到后台任务的回调时。
- 避免在多个屏幕实体(活动等)同时打开时处理我们的回调(一个 activity 在另一个之上)。它有效,因为当前只有一个屏幕实体在我们的屏幕上处于活动状态(另一个处于停止状态)。
最后一步。当我们想要 post 我们的片段中的某个事件或 activity (例如,在从异步服务器请求获得响应之后),我们应该使用我们的助手 class 中的 post 方法:
ExampleAsyncRequest exampleAsyncRequest = new ExampleAsyncRequest(
new Response.Listener<ExampleAsyncRequestResponse>() {
@Override
public void onResponse(ExampleAsyncRequestResponse response) {
EventBusHelper.INSTANCE.postStickyIfNotFinishing(OurFragment.this, response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(ExampleAsyncRequestError error) {
EventBusHelper.INSTANCE.postStickyIfNotFinishing(OurFragment.this, error);
}
});
为了在我们的总线中获取这些事件,我们使用下一个代码:
@Subscribe(sticky = true)
public void onExampleAsyncRequestResponse(ExampleAsyncRequestResponse response) {
EventBus.getDefault().removeStickyEvent(response);
...
}
@Subscribe(sticky = true)
public void onExampleAsyncRequestError(ExampleAsyncRequestError error) {
EventBus.getDefault().removeStickyEvent(error);
...
}
我们必须删除获得的粘性事件,以避免它们被另一个 activity 或当前位于顶部的片段处理。
当我们使用事件总线(来自 Guava)从服务器获取异步响应时 - 一切正常。但是,如果我们想在顶部打开相同 activity 的另一个实例,那么我们的订阅事件也将在底部处理(已停止)activity 导致不同来源的错误。
是否可以使事件总线的事件仅由当前顶部的单个订阅者处理activity?
有两种解决方法:
- 您订阅的地点和订阅前的活动请先取消订阅,然后再订阅。之后将在 eventbus 事件堆栈中一次只执行一个订阅。
- 我认为您有一个 BaseActivity,每当您创建一个时,事件总线订阅就会在每个 activity 上发生。为此,您可以在onresume中订阅,在onpause中取消订阅将解决您的问题。
当你在 activity re-creates 之前使用以下方法删除所有粘性事件:-
stickyEvent= EventBus.getDefault().getStickyEvent(classType);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// "Consume" the sticky event
EventBus.getDefault().removeStickyEvent(stickyEvent);
}
对于那些曾经利用事件总线范式来获取异步操作结果的人(并保持 activity 或片段的方向更改事件和正确的工作,即使我们当前打开了多个相同的活动),我建议以下样板实现。它基于Greenrobot的事件总线库,当然在这里使用任何其他库也不难。
首先,让我们创建一种助手class来为事件总线发送事件:
/**
* Helps to send sticky events avoiding them to be sent when the current screen (content entity)
* is about to be closed.
*/
public enum EventBusHelper {
/** Single instance. */
INSTANCE;
/**
* Posts sticky event to make activity fetch it (if activity is not finishing).
*
* @param activity An activity to check state.
* @param event An event to be fired.
* */
public void postStickyIfNotFinishing(@NonNull Activity activity, Object event) {
postStickyIfNotFinishing(activity.isFinishing(), event);
}
/**
* Posts sticky event to make fragment fetch it (if fragment is not finishing).
*
* @param fragment A fragment to check state.
* @param event An event to be fired.
* */
public void postStickyIfNotFinishing(@NonNull Fragment fragment, Object event) {
postStickyIfNotFinishing(fragment.isRemoving(), event);
}
/**
* Posts sticky event if a subscriber is not going to be finished.
*
* @param isFinishing True - if subscriber will be finished.
* @param event An event to be sent.
* */
private void postStickyIfNotFinishing(boolean isFinishing, Object event) {
if (!isFinishing)
EventBus.getDefault().postSticky(event);
}
此 class 的主要目的是仅当我们的 activity、片段(对话片段)不会关闭时才发送 Subscribe-methods 的事件。否则,当我们在 activity(片段等)的下一次启动时获取一些即时数据而没有首先触发我们的请求时,我们将得到不可接受的行为。但是当我们的屏幕实体(activity,片段)在屏幕方向改变后即将被重新创建时,这种事件发送方法不会阻止事件的发送。
下一步 - 是在我们的 activity 或片段:
的启动和停止操作上注册和注销事件总线/**
* Initializing event bus to process completed tasks.
* */
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
/**
* Stopping event bus to avoid background ops processing.
* */
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
有两个必要:
- 为了避免任何后台操作,当我们收到后台任务的回调时。
- 避免在多个屏幕实体(活动等)同时打开时处理我们的回调(一个 activity 在另一个之上)。它有效,因为当前只有一个屏幕实体在我们的屏幕上处于活动状态(另一个处于停止状态)。
最后一步。当我们想要 post 我们的片段中的某个事件或 activity (例如,在从异步服务器请求获得响应之后),我们应该使用我们的助手 class 中的 post 方法:
ExampleAsyncRequest exampleAsyncRequest = new ExampleAsyncRequest(
new Response.Listener<ExampleAsyncRequestResponse>() {
@Override
public void onResponse(ExampleAsyncRequestResponse response) {
EventBusHelper.INSTANCE.postStickyIfNotFinishing(OurFragment.this, response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(ExampleAsyncRequestError error) {
EventBusHelper.INSTANCE.postStickyIfNotFinishing(OurFragment.this, error);
}
});
为了在我们的总线中获取这些事件,我们使用下一个代码:
@Subscribe(sticky = true)
public void onExampleAsyncRequestResponse(ExampleAsyncRequestResponse response) {
EventBus.getDefault().removeStickyEvent(response);
...
}
@Subscribe(sticky = true)
public void onExampleAsyncRequestError(ExampleAsyncRequestError error) {
EventBus.getDefault().removeStickyEvent(error);
...
}
我们必须删除获得的粘性事件,以避免它们被另一个 activity 或当前位于顶部的片段处理。