我计划添加Otto事件总线来解耦我的通信。我想要使用事件总线的一件事是在按钮点击处理程序和活动之间进行通信。
这个想法是单击按钮(从我的自定义视图)将生成一个文本提交事件,该事件将通知活动。然后,活动将决定如何处理它。如果活动认为正确,它会将文本发送到服务上传或其他任何内容。
这是使用事件总线的正确方法吗?
此外,使用事件总线时有哪些好的做法?
答案 0 :(得分:1)
我仍然认为这个问题应该关闭,因为StackOverflow模型不合适。
但是对于任何想要 如何在线上组织用户事件 的人来说,这就是我们在我工作的地方所做的一切。
请记住,如果您正在创建一个实现高水平分离的大型项目,那么这种类型的结构才有意义,这使得开发团队的生活更加轻松。对于小型,快速的项目或测试应用程序来说太费力了。
PS:以下所有代码都是100%输入,而不检查任何实际代码,因此会出现拼写错误和小错误,但应足以了解该方法。我也没有写任何像@override
这样的注释,对它来说太懒了。
首先:活动会覆盖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();
}
}
然后:您拥有所有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" ?
}
}
我同意一些评论,当有“点击”事件通过公共汽车时,可能会创建一个巨大的,奇怪的意大利面条代码。但是,如果从一开始就定义了一个良好的结构化方法,并且所有开发人员都遵循它,那么您就可以实现一个易于遵循并且责任分离非常明确的项目。