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

Is it the proper way to use an event bus?

我计划添加 Otto 事件总线来解耦我的通信。我想要使​​用事件总线的其中一件事是在按钮单击处理程序和 activity 之间进行通信。

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

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

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

我仍然认为这个问题应该关闭,因为它不适合 Whosebug 模型。

但是对于正在查看 如何围绕总线组织用户事件的任何人来说,这就是我们在我工作的地方。

请记住,只有在创建一个大项目时,这种结构才有意义,在这个项目中实现高度分离可以使开发人员团队的工作更轻松。对于需要付出太多努力的小型快速项目或测试应用程序。

PS.: 下面的所有代码都是 100% 用心输入的,没有检查任何真实代码,所以会有拼写错误和小错误,但应该足以了解该方法。 @override之类的注解我也没有写,太懒了

首先:Activity 覆盖 getSystemService 以根据需要通过上下文和 register/unregister 事件处理程序提供总线。

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();
    }
}

Then:您将所有 RecyclerView.ViewHolder(或自定义小部件)作为点击侦听器并发送适当的事件。例如在照片项目的 ViewHolder 中。

public class PhotoHolder extends ViewHolder implements OnClickListener {

     TextView user;
     ImageButton like;
     ImageView photo;

     Photo data; // assume this was set during `bindViewHolder`

     public PhotoHolder(View itemView) {
          super(itemView);
          user = (TextView) itemView.findViewById(...
          like = (ImageButton) itemView.findViewById(...
          photo = (ImageView) itemView.findViewById(...

          user.setOnClickListener(this);
          like.setOnClickListener(this);
          photo.setOnClickListener(this);
     }

     public void onClick(View view){
          switch(view.getId()){
              case R.id.user:
                   ((Bus)view.getSystemService(BUS_SERVICE))
                              .post(new Event.PhotoEvent.UserTap(data);
                 break;
              case R.id.like:
                   ((Bus)view.getSystemService(BUS_SERVICE))
                              .post(new Event.PhotoEvent.LikeUnlike(data);
                 break;
              case R.id.photo:
                   ((Bus)view.getSystemService(BUS_SERVICE))
                              .post(new Event.PhotoEvent.PhotoTap(data);
                 break;
          }
     }
}

最后当然:是创建这些事件对象并将所有事件添加到适当的处理程序。

// 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" ?
     }
 }

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