18

I am new to android mobile development (Android Studio native development - for new knowledge). And here I want to ask a question regarding best practice for input validation. As far we know, when a developer develop input form. We need to prevent a user from key in a wrong input into the text field. So here is my question,

  1. Can we create one java file for validation purpose only? All input form ,must go to that one validation file only (In case of many input page screen in one apps). If YES, how can I get an example/link/tutorial of that technique for my learning study. If NO, why?

From my point of view personally, it should have a way to implement the technique. So that we didn't need to reuse same code all over again for each java file (in term of clean code). Unfortunately, I didn't find any example or tutorial for that. Maybe I search a wrong keyword or misread. And if there is no such technique exist, what are the best practice for input validation?

Thank you.

p/s: This thread for find a better way in best practice. Thank you.

Salehin Rafi
  • 341
  • 2
  • 7
  • 16
  • Actually there are some libs already https://github.com/vekexasia/android-edittext-validator and https://github.com/thyrlian/AwesomeValidation – Neil Oct 12 '15 at 03:05

2 Answers2

16

This java class implements a TextWatcher to "watch" your edit text, watching any changes done to the text:

public abstract class TextValidator implements TextWatcher {
    private final TextView textView;

    public TextValidator(TextView textView) {
        this.textView = textView;
    }

    public abstract void validate(TextView textView, String text);

    @Override
    final public void afterTextChanged(Editable s) {
        String text = textView.getText().toString();
        validate(textView, text);
    }

    @Override
    final public void 
    beforeTextChanged(CharSequence s, int start, int count, int after) {
         /* Needs to be implemented, but we are not using it. */ 
    }

    @Override
    final public void 
    onTextChanged(CharSequence s, int start, int before, int count) { 
         /* Needs to be implemented, but we are not using it. */    
    }
}

And in your EditText, you can set that text watcher to its listener

editText.addTextChangedListener(new TextValidator(editText) {
    @Override public void validate(TextView textView, String text) {
       /* Insert your validation rules here */
    }
});
ZooMagic
  • 497
  • 6
  • 13
Randyka Yudhistira
  • 3,527
  • 1
  • 26
  • 41
  • 1
    Is it a good pattern to pass instance of UI components to classes that should deal with only logic? I think better way would be to get validate response from validator class and in the implementation class use the value to manipulate the UI. – Ashish Dulhani Nov 21 '18 at 15:15
6

One approach (which I am using) is you should have a helper for validating inputs such as:

  1. Nullity (or emptiness)
  2. Dates
  3. Passwords
  4. Emails
  5. Numerical values
  6. and others

here's an exerpt from my ValidationHelper class:

public class InputValidatorHelper {
    public boolean isValidEmail(String string){
        final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
        Pattern pattern = Pattern.compile(EMAIL_PATTERN);
        Matcher matcher = pattern.matcher(string);
        return matcher.matches();
    }

    public boolean isValidPassword(String string, boolean allowSpecialChars){
        String PATTERN;
        if(allowSpecialChars){
            //PATTERN = "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})";
            PATTERN = "^[a-zA-Z@#$%]\\w{5,19}$";
        }else{
            //PATTERN = "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,20})";
            PATTERN = "^[a-zA-Z]\\w{5,19}$";
        }



        Pattern pattern = Pattern.compile(PATTERN);
        Matcher matcher = pattern.matcher(string);
        return matcher.matches();
    }

    public boolean isNullOrEmpty(String string){
        return TextUtils.isEmpty(string);
    }

    public boolean isNumeric(String string){
        return TextUtils.isDigitsOnly(string);
    }

    //Add more validators here if necessary
}

Now the way I use this class is this:

InputValidatorHelper inputValidatorHelper = new InputValidatorHelper();
StringBuilder errMsg = new StringBuilder("Unable to save. Please fix the following errors and try again.\n");
//Validate and Save
boolean allowSave = true;
if (user.getEmail() == null && !inputValidatorHelper.isValidEmail(user_email)) {
    errMsg.append("- Invalid email address.\n");
    allowSave = false;
}

if (inputValidatorHelper.isNullOrEmpty(user_first_name)) {
    errMsg.append("- First name should not be empty.\n");
    allowSave = false;
}

if(allowSave){
    //Proceed with your save logic here
}

You can call your validation by using TextWatcher which is attached via EditText#addTextChangedListener

example:

txtName.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        //Do nothing
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        validate();
    }
});
PinoyCoder
  • 1,102
  • 8
  • 13
  • There are Android special InputTypes for all the TextView types you've listed. Why do you need validation? – Zon Jul 04 '17 at 07:30