Пожалуйста, опишите ошибку

Нашли баг? Помогите нам его исправить, заполнив эту форму

Библиотека для валидации UI элементов. Android Saripaar

Олег Шелякин
Android-разработчик

При написании практически каждого Android приложения нам необходимо валидировать некоторые Views: EditText, CheckBox, Seekbar, RadioButton и даже Spinner. Это может быть простая проверка на соответствие регулярному выражению или более сложная, например, проверка View в определенной последовательности, валидирование при смене фокуса и т.д Эта задача является повседневной для любого Android разработчика. Она не является сложной, но все таки достаточно время затратная и часто повторяющаяся, также иногда требует достаточно большое количества кода. Существует много инструментов для реализации данной задачи более лаконично, быстро и самое главное очень просто. В данной статье я расскажу вам об Android Saripaar.

Вот ссылка на репозиторий https://github.com/ragunathjawahar/android-saripaar. Здесь вы можете посмотреть, как добавить библиотеку в свой проект. Так же там собрано большое количество примеров, используя которые, можно найти идеальное решение для вашей задачи.

Android Saripaar — это простая, очень мощная библиотека для валидирования UI элементов. Она основана на аннотациях и рефлексии. В примерах я буду использовать ButterKnife. Eсли вы не знакомы с этой библиотекой, можете почитать в моей статье: Оптимизация кода с помощью Butter Knife.

В самом простом варианте использования Android Saripaar достаточно просто добавить аннотации к валидируемому полю. Ниже пример:

@Email
@BindView(R.id.etEmail) EditText etEmail;

@NotEmpty
@BindView(R.id.etName) EditText etName;

@Password
@BindView(R.id.etPassword) EditText etPassword;

@ConfirmPassword
@BindView(R.id.etConfirmPassword) EditText etConfirmPassword;

Далее необходимо добавить класс Validator, который реализует всю логику валидации.

private Validator validator;

Для того чтобы создать экземпляр, в его конструктор мы должны передать объект, называемый контроллером, то есть тот объект, в котором содержатся Views. Как правило это Activity или Fragment. Также контроллер должен реализовать интерфейс ValidationListener. Ниже пример:

private Validator validator;

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   ButterKnife.bind(this);
   setSupportActionBar(toolbar);

   validator = new Validator(this);
   validator.setValidationListener(this);
}

@Override
public void onValidationSucceeded() {
    //your code here!
}

@Override
public void onValidationFailed(List errors) {
   for (ValidationError error : errors) {
       String errorText = error.getCollatedErrorMessage(this);
       ((EditText)error.getView()).setError(errorText);
   }
}

Как видно, данный интерфейс содержит два метода, которые будут выполняться: 1) onValidationSucceeded — при выполнении всех правил; 2) onValidationFailed — при нарушении одного и более правил. Как вы заметили, второй метод принимает в аргумент метода коллекцию ошибок — List<ValidationError>. ValidationError — класс который содержит Views, не прошедшие валидацию, и сами правила, которые были провалены. С помощью метода getCollatedMessage мы можем получить сообщения об ошибках от множества нарушенных правил.

Rule

Мы также можем создавать свои собственные Rules. Этого можно достичь двумя способами. Первый способ заключается в использовании так называемого абстрактного класса QuickRule:

validator.put(etName, new QuickRule() {
   @Override
   public boolean isValid(EditText view) {
       return view.getText().toString().length() > 6;
   }

   @Override
   public String getMessage(Context context) {
       return "Invalid length. It shouldn't be no less than 6";
   }
});

Мы можем добавить сколько угодно правил к одному View, метод put принимает любое количество аргументов типа QuickRule. Это не повлияет на правила, которые добавлены с помощью аннотаций. То есть они просто добавляются к текущим.

Второй способ заключается в написании собственных аннотаций и их обработчика. Ниже пример:

@ValidateUsing(ContainRule.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Contain {
   String containedString() default "SML";
   int sequence()       default -1;
   int messageResId()   default -1;
   String message()     default "It should contain SML";
}

Далее необходимо создать класс, наследуемый от абстрактного класса AnnotationRule, и реализовать всего один метод:

public class ContainRule extends AnnotationRule {

   protected ContainRule(Contain name) {
       super(name);
   }

   @Override
   public boolean isValid(String s) {
       return s.contains(mRuleAnnotation.containedString());
   }
}

Теперь нужно также добавить эту аннотацию к полям, которые необходимо валидировать по этому правилу:

@NotEmpty
@Contain
@BindView(R.id.etName) EditText etName;

И последнее, что необходимо сделать, это зарегистрировать аннотацию в классе Validator.

Validator.registerAnnotation(Contain.class);

В остальном все также.

Mode

Validator может валидировать наши Views в двух режимах:

validator.setValidationMode(Validator.Mode.IMMEDIATE);
validator.setValidationMode(Validator.Mode.BURST);

IMMEDIATE mode — останавливает валидирование после первого View, которое нарушает все правила. Требует упорядоченные (@Order) правила. BURST mode — валидирует все Views по всем правилам.

BURST

IMMEDAITE

Если наши Views имеют аннотацию @Order, мы можем использовать для валидации такие методы, как:

validator.validateBefore(v);
validator.validateTill(v);

В первом случае валидируются все Views до переданного в аргумент метода, во втором все Views, включая переданный в метод.

validateBefore

validateTill

Ниже приведен пример использования метода validateBefore вместе с аннотацией от ButterKnife@OnFocusChange.

@OnFocusChange(value = {R.id.etEmail, R.id.etName, R.id.etPhone, R.id.etPassword, R.id.etConfirmPassword})
void onFocusChanged (View v,  boolean hasFocus){
   if (hasFocus){
       validator.validateBefore(v);
   }
}

На этом все. В этой статье приведены основные возможности библиотеки Saripaar. Работать с ней одно удовольствие, она сильно сокращает код и выполняет простые, но частые задачи без ошибок. А также реализует в себе различные способы и возможности для более гибкого валидирования Views. Спасибо, что дочитали. Надеюсь эта статья была для вас полезной!

Читать и комментировать