2016-03-04 3 views
1

Я пытаюсь изучить некоторые RxJava и RxAndroid, и я думаю, что проблема, которую я могу, легко сделать с помощью такого инструмента. Вот проблема: Мы могли бы «N» количество просмотров в Activity, и каждый из них используется для удовлетворения некоторого состояния. Когда пользователь нажимает «Сохранить», мы хотим проверить, соблюдены ли все условия во всех представлениях, а если нет, попросите пользователя подтвердить их отдельно. Так вот пример того, как я хотел бы иметь дело с этой проблемой без RxJava:Chained RxJava вызывает поток пользовательского интерфейса

private void validation(List<CustomView> views) 
{ 
    for (CustomView view : views) 
    { 
     if (view.metCondition() == false) 
     { 
      showConfirmationDialog(view); 
      return false; 
     } 
    } 

    return true; 
} 


private void showConfirmationDialog(CustomView view) 
{ 
    ConfirmationDialog dialog = new ConfirmationDialog(this, view); 

    dialog.show(); 
} 

private void dialogResult(CustomView view) 
{ 
    view.setCondition(true); 

    validation(mViews); 
} 

Очевидно, что я бы своего рода слушателя за результат подтверждения и после того, состояние подтверждено (с ОК или Отмена) для параметра view.metCondition() будет установлено значение true, чтобы он снова не появлялся для этого представления. И, конечно же, после того, как «validation» вернет true, она будет запускать функцию «Сохранить()».

Это действительно модный показ моего реального решения, поскольку я хотел сохранить его как можно более простым, так что просто комментируйте, если вы знаете, как можно сделать что-то подобное с RxJava. Я уже использую библиотеку для некоторых асинхронных файлов (разговаривая с устройствами, подключенными к USB), поэтому я кое-что знаю, но никогда не знал, как цепочка вызовов, подобных этому.

Любая помощь очень ценится.

Редактировать

добавлен метод слушателя, чтобы мы могли видеть, что функция «Validate()» вызывается снова

ответ

3

Для прикован проверки, вы действительно должны смотреть в combineLatest()operator. Сначала вы создаете Observable за каждые View, а затем используете этот оператор. RxBinding - отличное расширение для Android-просмотров.

См. this пример. Это хорошая проверка.

+0

Это очень хороший пример того, что мне нужно, но мне потребовалось некоторое время, чтобы это понять. Большое спасибо. –

0

Просто еще один пример для вдохновения :)

private static class CustomViewValidator { 
    //Subject can be attach to other sources eg. EditText etc 
    //Of course it can be replaced with simple variable 
    BehaviorSubject<Boolean> mSubject = BehaviorSubject.create(); 

    Observable<Boolean> getValidationObservable() { 
     return mSubject.asObservable().map(s -> { 
      if (!s) { 
       throw new ViewValidationThrowable(CustomViewValidator.this); 
      } else { 
       return true; 
      } 
     }); 
    } 

    void setCondition(boolean v) { 
     mSubject.onNext(v); 
    } 
} 

private static class ViewValidationThrowable extends RuntimeException { 
    //custom Exception let us to keep reference to invalid View 
    private final CustomViewValidator mView; 

    private ViewValidationThrowable(CustomViewValidator view) { 
     mView = view; 
    } 
} 

private List<CustomViewValidator> mViews; 

private void validate(final List<CustomViewValidator> viewObservables) { 

    Observable.from(viewObservables) 
      .flatMap(CustomViewValidator::getValidationObservable) 
      .subscribe(aBoolean -> { 
         //we can just ignore all items 
        }, 
        throwable -> { 
         if (throwable instanceof ViewValidationThrowable) { 
          CustomViewValidator view = ((ViewValidationThrowable) throwable).mView; 
          //show dialog here 
         } 
        }, 
        () -> { 
         //everything valid 
        }); 
} 

private void dialogResult(CustomViewValidator view) { 
    view.setCondition(true); 
    validate(mViews); 
} 

В этом примере мы еще нужно вызвать validate методы каждый раз, когда мы хотим сделать проверку.

Вот еще один пример, когда мы не сломаем цепочку.

private static class Pair<T,V> { 
    private final T first; 
    private final V second; 

    public Pair(T first, V second) { 
     this.first = first; 
     this.second = second; 
    } 
} 
private static class CustomViewValidator { 
    //Subject allows us: 
    // * probably not break chain later using some retry techniques 
    // * subject can be attach to other sources eg. EditText etc 
    //Of course it can be replaced with simple variable 
    BehaviorSubject<Boolean> mSubject = BehaviorSubject.create(); 

    Observable<Pair<Boolean,CustomViewValidator>> getValidationObservable() { 
     return mSubject.asObservable().map(s -> new Pair<>(s,CustomViewValidator.this)); 
    } 

    void setCondition(boolean v) { 
     mSubject.onNext(v); 
    } 
} 

private void validate(final List<Observable<Pair<Boolean, CustomViewValidator>>> viewObservables) { 
    //IMPORTANT do not forget to unsubscribe 
    // In this case we do not break our chain, so it can last forever 
    Subscription subsciption = Observable.combineLatest(viewObservables, 
      objects -> { 
       for (Object object : objects) { 
        Pair<Boolean, CustomViewValidator> viewPair = (Pair<Boolean, CustomViewValidator>) object; 
        if (!viewPair.first) { 
         return viewPair; 
        } 
       } 
       return new Pair<>(true, null); 
      }) 
      .subscribe(pair -> { 
       if (pair.first) { 
        //everything is valid DO NOT USE second argument here 
       } else { 
        //show dialog here using pair.second as View 
       } 
      }); 

} 

private void dialogResult(CustomViewValidator view) { 
    view.setCondition(true); 
    //no reason to call validate again 
    //setCondition will trigger chain again 
} 

К сожалению, я не проверял его. Просто попытался дать вам основную идею разных подходов. Эти подходы в значительной степени основаны на идеях, уже выраженных в принятом ответе.

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