0

How good is using a common generic textwatcher for whole project in terms of performance and optimization?In my project I am using many editext and each edittext has listener to be implemented. I created a generic text watcher like this.Since in each listener i need to access other views of screen i am passing those views in constructor.While the below approach improves readibility of code it does introduces a casting overhead.Is it good practice to follow this approach?Is there any better approach i can follow?-

public class GenericTextWatcher implements TextWatcher {

    private View view,view2,view3,view4;
    public  GenericTextWatcher(View view) {
        this.view = view;
    }
    public GenericTextWatcher(View view,View view2,View view3) {
         this.view = view;
        this.view2=view2;
        this.view3=view3;
     }
    public GenericTextWatcher(View view,View view2) {
        this.view = view;
        this.view2=view2;
    }
    public GenericTextWatcher(View view,View view2,View view3,View view4) {
        this.view = view;
        this.view2=view2;
        this.view3=view3;
        this.view4=view4;
    }

    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        switch (view.getId())
        {
            case R.id.etMfafasf:
                if (((EditText)view).getText().length()==8 &&((EditText)view2).getText().length()>0)
                    ((TextView)view3).setEnabled(true);
                else
                    ((TextView)view3).setEnabled(false);
                break;
            case R.id.etModaDFFSA:
                if (((EditText)view2).getText().length()>0 &&((EditText)view).getText().length()==8)
                    ((TextView)view3).setEnabled(true);
                else
                    ((TextView)view3).setEnabled(false);
               ValidationUtils.checkfasffsfimit(charSequence,(TextInputLayout)view4);
                break;

            case R.id.etMoXYZ:
                if (((EditText)view).getText().length()==8)
                    ((TextView)view2).setEnabled(true);
                else
                    ((TextView)view2).setEnabled(false);
                break;
        }
    }

    public void afterTextChanged(Editable editable) {

    }
}

Calling TextWatcher

etNumber.addTextChangedListener(new GenericTextWatcher(etNumber,tvNdf));
Android Developer
  • 9,157
  • 18
  • 82
  • 139

2 Answers2

1

I suppose you could develop this in a more structured manner if you wish to avoid the type casting cost at the runtime.

public class GenericTextWatcher implements TextWatcher {

    private EditText[] mEditArray;
    private TextView[] mTextArray;

    public  GenericTextWatcher(EditText[] editArray, EditText textArray) {
        mEditArray = editArray;
        mTextArray = textArray;
    }

    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        switch (view.getId())
        {
            case R.id.etMfafasf:

                EditText view= mEditArray[0], view2 = mEditArray[1];

                TextView view3 = mTextArray[0]; 
                if (view.getText().length()==8 && view2.getText().length()>0)
                    view3.setEnabled(true);
                else
                    view3.setEnabled(false);
                break;

            case R.id.etModaDFFSA:
                EditText view= mEditArray[0], view2 = mEditArray[1];

                TextView view3 = mTextArray[0]; 
                if (view2.getText().length()>0 && view.getText().length()==8)
                    view3.setEnabled(true);
                else
                    view3.setEnabled(false);
               ValidationUtils.checkfasffsfimit(charSequence,(TextInputLayout)view4);
                break;

            case R.id.etMoXYZ:
                EditText view= mEditArray[0], view2 = mEditArray[1];

                if (view.getText().length()==8)
                    view2.setEnabled(true);
                else
                    view2.setEnabled(false);
                break;
        }
    }
 }

And you could call this allocate a listener this way :

etNumber.addTextChangedListener(
new GenericTextWatcher(new EditText[]{etNumber}, new TextView[]{tvNdf}));

This will make it cleaner since you are overloading the constructors based on number of arguments... This mayn't be the best design since tomorrow let's say you'll need a constructor with 10 views, your overloaded constructor will grow like GenericTextWatcher(view, view1, view2 ...., view9)

Adithya Upadhya
  • 2,239
  • 20
  • 28
0

Your code will work fine. But if you want best practices, I suggest publish/subscribe.

For example EventBus from Google Guava Library - "Publish-subscribe-style communication between components without requiring the components to explicitly register with one another".

Here is an example,

In your activity or fragment, create an event bus

EventBus eventBus = new EventBus();

Register the objects that will listen (subscribe) to events. In this case it will be your activity or fragment

eventBus.register(this);

Then create a class that will be your event

public class EditEvent {
     private CharSequence charSequence, int i, int i1, int i2, int id; // add getters and setters
     public EditEvent(CharSequence charSequence, int i, int i1, int i2, int id)
     {//...}
}

Then subscribe to the event in your activity or fragment by using the @Subscribe annotation

@Subscribe // this will be called when an EditEvent is posted to the bus
public void handleTextChange(EditEvent event) {
     switch (event.id)
     {
           //...
     }
}

Finally, at each view's watcher, post the event

onTextChanged(CharSequence s, int start, int before, int count)
{
       eventBus.post(new EditEvent(s, start, before, count, EditText.this));
}
Ahmed Ghonim
  • 4,455
  • 1
  • 17
  • 23