gpt4 book ai didi

android - 具有线程安全性的事件总线的最佳实践

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:24:14 25 4
gpt4 key购买 nike

我的应用程序具有用于用户交互的 Activity 和后台服务,这是唯一修改数据模型的地方。后台服务监听用户执行的操作以及来自网络的传入消息。因此可能会出现并发问题,我试图通过使用处理程序来防止这些问题。对于事件层,我使用 greenrobots Eventbus。

这一切都运行良好,但我想知道是否有更智能/更快/代码更少(因此更不容易出错)的方式来处理这个用例?

更具体地说:

  • 有没有办法确保 onEvent 方法的串行执行没有处理程序?
  • 有没有 onEvent 方法的替代方法对于每个可能的事件?
  • 我有更好的模式吗在这里做什么?

这是我的方法:

在 oncreate 方法中,我会注册服务(如果有 Activity ,我会在 onstart 中执行此操作)

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

在 onDestroy 中,我再次注销:

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

每当我对传入事件使用react时,我都想确保串行执行,因为可能会出现并发问题,因为存在来自用户交互以及通过网络来自其他用户的传入事件。所以我决定使用处理程序:

private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Object receivedEvent = msg.obj;
if(receivedEvent instanceof EditUser)
{
processEditUserBroadcast((EditUser)receivedEvent);
}
else if(receivedEvent instanceof JoinParty)
{
processJoinPartyBroadcast((JoinParty)receivedEvent);
}
else if(receivedEvent instanceof LeaveParty)
{
processLeavePartyBroadcast();
}
else if(receivedEvent instanceof SendMessage)
{
processSendMessageBroadcast((SendMessage)receivedEvent);
}
else if(receivedEvent instanceof ReceivedMessage)
{
processReceivedMessageBroadcast((ReceivedMessage)receivedEvent);
}
else if(receivedEvent instanceof Reset)
{
processResetBroadcast();
}
else if(receivedEvent instanceof ImageDownloadFinished)
{
processImageDownloadFinishedBroadcast((ImageDownloadFinished)receivedEvent);
}
}
};
return handler;
}

对于每个感兴趣的事件,我都有一个 onEvent 方法,它只是将事件传递给处理程序,以确保通过一个小的“passToHandler”辅助函数串行执行

public void passToHandler(Handler handler, Object object)
{
Message message = handler.obtainMessage();
message.obj = object;
handler.sendMessage(message);
}

public void onEvent(EditUser editUser)
{
passToHandler(handler,editUser);
}

public void onEvent(JoinParty joinParty)
{
passToHandler(handler,joinParty);
}

public void onEvent(LeaveParty leaveParty)
{
passToHandler(handler,leaveParty);
}

public void onEvent(SendMessage sendMessage)
{
passToHandler(handler,sendMessage);
}

public void onEvent(ReceivedMessage receivedMessage)
{
passToHandler(handler,receivedMessage);
}

public void onEvent(Reset reset)
{
passToHandler(handler,reset);
}

public void onEvent(ImageDownloadFinished imageDownloadFinished)
{
passToHandler(handler,imageDownloadFinished);
}

“过程..”方法是“数据魔法”发生的地方,不应该与我的问题相关。

当然,对于每个可能发生的事件,我确实创建了一个类,它通常像这样非常 slim :

public class JoinParty {
private String partyCode;

public JoinParty(String partyCode) {
super();
this.partyCode = partyCode;
}
public String getPartyCode() {
return partyCode;
}
}

最佳答案

感谢您发布此 Matthias!我认为您提出了关于 GreenRobot EventBus 的线程安全的一个非常重要的观点,它的用户很容易忽略这一点。

虽然我是 GreenRobot EventBus 和 Android(但不是 Java)的新手,但我认为您很可能正朝着正确的方向前进。如果我正确阅读了 GreenRobot EventBus 源代码,这种方法的另一个可能的好处是将 SendMessage 事件发布到您的 onEvent() 方法会立即返回(在处理程序上调用 sendMessage 之后),从而允许 EventBus 继续将其发布到任何其他订阅者,而不会延迟您类(class)的实际处理。不过,这可能是您想要的,也可能不是。

使用您提供的方法,您需要确保的另一件事是,如果您采用这样的方法,则您的类没有其他公共(public)方法具有您的所有 onEvent() 方法和方法作为 processEditUserBroadcast()。否则,虽然您已确保从 EventBus 接收到的事件的所有处理实际上都在单个线程上处理(以串行方式),但其他一些类可能会在不同的线程上调用此类的公共(public)方法,然后导致你又遇到安全问题了。

如果您知道您确实需要在此类上支持其他公共(public)方法,那么按照您在此处所做的操作至少将所有 onEvent() 方法处理到单个线程(创建线程的 Looper 的线程) Looper 从我在 Looper 类的文档中读到),这至少简化了一些事情。然后,您可能还需要对公共(public)方法和所有其他方法(例如 processEditUserBroadcast())应用一些同步,以确保在您要使用其他公共(public)方法时从多个线程安全访问该类的数据成员这节课。或者,根据这些数据成员是什么以及您的需求,您可以简单地使其中一些成为 volatile 、原子性或使用并发集合等。这完全取决于读写访问权限需求是这些访问所需的粒度。

这有帮助吗?对于那些精通 Android、Loopers、Handlers、GreenRobot EventBus 等的人,我有没有说错?

关于android - 具有线程安全性的事件总线的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27793763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com