2016-02-24 2 views
1

Я планирую добавить автобус событий Otto, чтобы отключить мои сообщения. Одна из вещей, которые я хочу использовать для шины событий, - это связь между обработчиком нажатия кнопки и активностью.Правильно ли это использовать шину событий?

Идея состоит в том, что нажатие кнопки (из моего пользовательского представления) создаст событие отправки текста, которое сообщит об активности. Затем действие решит, что с ним делать. Если действие сочтет это правильным, оно отправит текст в службу для загрузки или что-то еще.

Это правильный способ использования автобуса событий?

Кроме того, что такое хорошая практика при использовании автобусов событий?

+3

«Это правильный способ использования автобуса событий?» - «правильно» очень субъективно.Я бы не использовал для этого шину событий, так как я не вижу здесь значения только при использовании прослушивателя. Я использую шины событий для связи между компонентами (например, service-> activity), где более четкая связь является более важной. – CommonsWare

+0

В целом используйте их как можно меньше. Они облегчают некоторые проблемы, когда то, что вы пытаетесь сделать, становится сложным в сложной архитектуре, потому что у модуля нет всех необходимых ему данных, но это само определение кода спагетти. Если есть другое возможное решение, используйте его. –

+1

Попробуйте не использовать (или просто - не использовать) шину событий для 'OnClickListener'. Отблагодаришь позже. Нет никакой реальной необходимости отделять кнопку от ее поведения, но это зависит от вас. – Shark

ответ

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

Я согласен с некоторыми из комментариев, возможно cr выйдем из огромного, странного кода спагетти, когда происходит «кратковременное» событие, проходящее через автобус. Но если с самого начала определяется хороший структурированный подход, и все разработчики следуют за ним, вы можете достичь проекта, который легко отслеживать и с очень четким разделением обязанностей.

Смежные вопросы