0

I am working on a unit converter app. It gets value from EditText and multiply it with values from string array and again stores in another array. Then displays it in ListView. But the EditText textwatcher is working slow. Why?

etarea.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (etarea.getText().length() > 0){
                    double b = Double.parseDouble(etarea.getText().toString());
                    for(int i = 0; i <= valueSpinner.length -1; i++){
                        double a = Double.parseDouble(valueSpinner[i].toString());
                        double c = b*a;
                        DecimalFormat df = new DecimalFormat(decimal);
                        valueet[i] = df.format(c);
                    }
                    viewHolder.tvvalue.setText(valueet[i]);
                    tvareavalue.setText(valueet[posonclick]);
                }else{
                    viewHolder.tvvalue.setText("Enter Value");
                }
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
  • My suggestion would be to use `Handler ` and `Runnable`. Move all your logic to another method, and implement it like [this](https://stackoverflow.com/a/14660979/8198240). Good practice is to wait until user finished typing. – sharp Jul 14 '17 at 12:59

1 Answers1

0

I think it's slow because you're doing a heavy work in your onTextChanged method of your TextWatcher.

You can put a trash hold time for user inputs (fox example 1 second) and after user finishes typing you can do your work.

There're several ways to handle this.

First you can create a Handler and listen user input. After your trash hold time you can do what you want.

// Create a handler.
private Handler handler = new Handler();

Create a runnable which does your job.

final Runnable runnable = new Runnable() {

     @Override
     public void run() {
          if (etarea.getText().length() > 0){
                    double b = Double.parseDouble(etarea.getText().toString());
                    for(int i = 0; i <= valueSpinner.length -1; i++){
                        double a = Double.parseDouble(valueSpinner[i].toString());
                        double c = b*a;
                        DecimalFormat df = new DecimalFormat(decimal);
                        valueet[i] = df.format(c);
                    }
                    viewHolder.tvvalue.setText(valueet[i]);
                    tvareavalue.setText(valueet[posonclick]);
                }else{
                    viewHolder.tvvalue.setText("Enter Value");
                }
     }       
}

And post it in your TextWatcher's afterTextChanged method.

public void afterTextChanged(Editable s) {
      handler.removeCallbacks(runnable); 
      handler.postDelayed(runnable, YOUR_TRASH_HOLD_TIME);
}

For a second way, you can use RxJava Debounce operator for handling this.

    // First create your observable
    Observable<OnTextChangeEvent> yourTextChangeObservable = WidgetObservable.text(yourInputText);

    // And create your subscription
    yourTextChangeSubscription = yourTextChangeObservable
      .debounce(YORU_TRASH_HOLD_TIME, TimeUnit.MILLISECONDS)
      .map(OnTextChangeEvent::text)
      .map(CharSequence::toString)
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(s -> {
                // do your work here with your input
            }
        );

You can get some more info about Debounce operator from here.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
savepopulation
  • 11,736
  • 4
  • 55
  • 80