Android 这是使用事件总线的正确方式吗?

Android 这是使用事件总线的正确方式吗?,android,events,otto,Android,Events,Otto,我计划添加Otto事件总线,以解耦我的通信。我希望使用事件总线的一个目的是在按钮单击处理程序和活动之间进行通信 这个想法是,按钮单击(从我的自定义视图)将生成一个文本提交事件,该事件将通知活动。然后,活动将决定如何处理它。如果活动认为合适,它会将文本发送到服务进行上传或其他任何操作 这是使用事件总线的正确方式吗 另外,在使用事件总线时,有哪些好的做法?我仍然认为这个问题不适合StackOverflow模型 但是,对于任何关注how on的人来说,how on可以围绕公交车组织用户活动,这就是我们

我计划添加Otto事件总线,以解耦我的通信。我希望使用事件总线的一个目的是在按钮单击处理程序和活动之间进行通信

这个想法是,按钮单击(从我的自定义视图)将生成一个文本提交事件,该事件将通知活动。然后,活动将决定如何处理它。如果活动认为合适,它会将文本发送到服务进行上传或其他任何操作


这是使用事件总线的正确方式吗


另外,在使用事件总线时,有哪些好的做法?

我仍然认为这个问题不适合StackOverflow模型

但是,对于任何关注how on的人来说,how on可以围绕公交车组织用户活动,这就是我们在我工作的地方所做的

请记住,只有在创建一个大型项目时,这种类型的结构才有意义,在这个项目中,实现高水平的分离可以使开发团队的生活更轻松。对于小的、快速的项目或测试应用来说,这太费劲了

注:下面所有的代码都是100%由心输入的,没有检查任何真正的代码,因此会有打字错误和小错误,但应该足以了解方法。我也没有写任何注释,比如
@override
,太懒了

First:活动重写
getSystemService
以通过上下文提供总线,并根据需要注册/取消注册事件处理程序

public MyActivity extends AppCompatActivity {
    private static final String BUS_SERVICE = "bus_service";

    private List<EventHandler> eventHandlers = new ArrayList();
    private Bus bus = new Bus();

    public void onCreate(Bundle savedState){
        super.onCreate(savedState);
            .... layout creation, etc, etc, etc

            if(isLoggedIn()) {
                eventHandlers.add(new LoggedUserNavigationHandler());
                eventHandlers.add(new RestPostRequestHandler());
            } else{
                eventHandlers.add(new GuestUserNavigation());
            }
            eventHandlers.add(new AnalyticsTrackingHandler());

            if(DEBUG) {
                // log all events in debug mode
                eventHandlers.add(new EventHandler(){
                             @Subscribe
                             public void onEvent(Object o){
                                 Log.d(TAG, "Event: " + o.toString);
                             }
                        });
            }

        }   
    }

    public Object getSystemService(String name){
        if(BUS_SERVICE.equals(name)) return bus;
        else return super.getSystemService(name);
    }

    public void onStart(){
        super.onStart();
        for(int i=0, size=eventHandlers.size(); i<size; i++) {
             eventHandlers.get(i).activity = this; // pass reference, might be usefull
             bus.register(eventHandlers.get(i));
        }
    }
    public void onStop(){
        for(int i=0, size=eventHandlers.size(); i<size; i++) {
             bus.unregister(eventHandlers.get(i));
             eventHandlers.get(i).activity = null;
        }
        super.onStop();
    }
}
最后一步当然是创建这些事件对象,并将所有事件添加到相应的处理程序中

// add all the app events under this class, or maybe create a `Event` package and then all the events in that package
public final class Event {

    public static class PhotoEvent {
          public final Photo data;
          public Photo(Photo data){
              this.data=data;
          }

          public static class UserTap extends PhotoEvent{
                // copy matching constructor
          }

          public static class LikeUnlike extends PhotoEvent{
                // copy matching constructor
          }

          public static class PhotoTap extends PhotoEvent{
                // copy matching constructor
          }

    }
}
最后,处理事件

public class RestPostRequestHandler {

     @Subscribe
     public void onPhotoLikeUnlike(Event.Photo.LikeUnlike event){
         // make your POST request here
     }
}
用于导航的处理程序:

public class LoggedUserNavigationHandler extends EventHandler{

     @Subscribe
     public void on(Event.Photo.UserTap event){
          Intent i = new Intent( ... create here intent for the "user profile"
          // activity reference was passed during onStart
          activity.startActivity(i);
     }
}
用于分析的处理程序:

 public class AnalyticsTrack {
     @Subscribe
     public void on(Event.Photo.UserTap event){
          // send event "user tap" ?
     }
 }

我同意一些评论,当“点击”事件通过总线时,可能会创建一个巨大、奇怪的意大利面代码。但是,如果从一开始就定义了一个良好的结构化方法,并且所有开发人员都遵循它,那么您就可以实现一个易于遵循且责任划分非常明确的项目。

“这是使用事件总线的正确方式吗?”——“正确”是非常主观的。我不会为此使用事件总线,因为我看不到仅仅使用侦听器的价值。我使用事件总线在松散耦合更为关键的组件(例如,服务->活动)之间进行通信。一般来说,尽可能少地使用它们。当您试图在复杂的体系结构中执行的操作变得困难时,它们确实可以缓解一些问题,因为模块没有它所需要的所有数据,但这正是意大利面代码的定义。如果有任何其他可能的解决方案,请使用它。尽量不要(或者干脆-不要)将事件总线用于
OnClickListener
。以后谢谢我。没有必要将按钮从其行为中分离出来,但这取决于您。我完全同意@commonware的说法,即“这是一种正确的方式”不是询问StackOverflow问题的方式,我也会投票关闭它,但我会根据我的经验来权衡。我工作的应用程序使用100%的用户生成的事件通过Otto bus,我非常喜欢它(但你看起来像是主观的)。然后我们有不同的类来处理
应用程序导航
RESTAPI POST
分析
事件。该活动只需在总线中注册/注销这些类。很好的例子是,我们对登录用户或来宾用户有不同的处理程序。@LittleChild我刚刚发布了它。哇,打字花的时间比我希望的要长。我只建议在大型项目、小型项目或测试项目中做类似的事情,这样做只会浪费时间。
 public class AnalyticsTrack {
     @Subscribe
     public void on(Event.Photo.UserTap event){
          // send event "user tap" ?
     }
 }