AutoCompleteTextView, TextWatcher to EditText

Second pass, deeper: AutoCompleteTextView's adapter + threshold machinery, and TextWatcher's 3 callbacks dissected: before, during and after every keystroke, powering mobile live search.

12 min read · 9 cards · 2 checks

Read in: English · हिन्दी · ગુજરાતી


Theory

You have met this widget; now meet its machinery

The syllabus sends you back to a BCA305-02 acquaintance: AutoCompleteTextView and TextWatcher closed FestConnect Mobile-1. A revisit is not a rerun: last year you WIRED them; this year you should be able to explain the machinery and answer the deeper questions.

And you have new context: in BCA405-01 you built live search on the web with keyup and AJAX. Today's lesson is that same pattern's mobile twin, and the parallel is the fastest way to master both.

Theory

AutoCompleteTextView: the recap, tightened

An AutoCompleteTextView is an EditText subclass that drops down filtered suggestions as the user types:

  • suggestions come from an ArrayAdapter (the ListView lesson's middleman again), stock row simple_dropdown_item_1line
  • setThreshold(n): how many characters before suggestions appear; the default is 2, and values below 1 are treated as 1
  • it suggests, never restricts: free text remains typeable, so validate getText() if only listed values are legal

One string per suggestion = stock adapter; richer dropdown rows = custom adapter: the ListView decision rule, verbatim.

Theory

TextWatcher: the 3 moments of one keystroke

A TextWatcher (attached with addTextChangedListener) hears every text change through 3 methods, in strict order:

  • beforeTextChanged(s, start, count, after): the OLD text, an instant before the change: s still reads "Garb"
  • onTextChanged(s, start, before, count): the NEW text, just landed: s reads "Garba": the live-search moment
  • afterTextChanged(Editable s): last, and the only one handed an Editable you may modify

Most real work lives in onTextChanged (react) or afterTextChanged (edit); before is for comparing old with new.

Practical

Search box with suggestions AND a live counter

public class SearchActivity extends AppCompatActivity {
    String[] events = { "Garba Night", "Coding Contest", "Robo Race",
                        "Rangoli", "Quiz Bowl" };

    @Override
    protected void onCreate(Bundle b) {
        super.onCreate(b);
        setContentView(R.layout.activity_search);

        AutoCompleteTextView box = findViewById(R.id.searchBox);
        box.setAdapter(new ArrayAdapter<>(this,
                android.R.layout.simple_dropdown_item_1line, events));
        box.setThreshold(1);                    // suggest from letter 1

        box.addTextChangedListener(new TextWatcher() {
            public void beforeTextChanged(CharSequence s, int start,
                                          int count, int after) { }

            public void onTextChanged(CharSequence s, int start,
                                      int before, int count) {
                int hits = 0;                   // live results counter
                for (String e : events)
                    if (e.toLowerCase().contains(s.toString().toLowerCase()))
                        hits++;
                lblCount.setText(hits + " matching events");
            }

            public void afterTextChanged(Editable s) { }
        });
    }
}

Quiz

The box shows "Garb" and the user types a. In which TextWatcher method does s FIRST read "Garba", making it the right hook for live search?

  1. beforeTextChanged: it fires first, so it has the newest text
  2. onTextChanged: it fires as the new text lands; beforeTextChanged still saw "Garb"
  3. afterTextChanged: only it ever sees the new text
  4. All 3 receive "Garba"; only their timing differs
Show the answer

onTextChanged: it fires as the new text lands; beforeTextChanged still saw "Garb"

The 3 methods split one keystroke into old, new and settled: beforeTextChanged fires first BUT carries the pre-change text ("Garb"): firing order and text freshness are different axes, which is exactly the confusion this question hunts. onTextChanged delivers the new text the moment it lands: the live-search hook, playing the role keyup played in BCA405-01's web version. afterTextChanged also sees "Garba" (option C's half-truth) but fires last and exists for EDITING via its Editable, not for first reaction.

Think first

The watcher that watched itself forever

A classmate wants typed text auto-capitalised, so inside afterTextChanged he calls s.replace(...) with the capitalised version: and the app freezes. Trace why, using what a watcher watches, then name the guard.

Show the answer

His replace() CHANGES the text: which is a text change: which fires the watcher again: which replaces again: an infinite loop of self-triggered callbacks freezing the main thread. The guard: make the edit conditional so an already-capitalised text is left untouched (if the first letter is already uppercase, return): then the second pass changes nothing and the cycle dies. General law: any watcher that modifies what it watches must be idempotent: running it on its own output must be a no-op. This is THE classic TextWatcher exam trap.

Watch out

Second-pass traps (the deeper set)

All 3 methods must exist: TextWatcher is an interface; implement even the ones you leave empty, or it will not compile.

Editing outside afterTextChanged: only its Editable is yours to modify; the CharSequences of the other 2 are read-only views.

Suggestion is not validation: free text still enters an AutoCompleteTextView; check the final value against the list if it must match.

Heavy work per keystroke: onTextChanged fires constantly; slow code there makes typing lag: keep it light.

Theory

One pattern, two platforms

Set the twins side by side: web live search = keyup event + AJAX + repaint the list; mobile = onTextChanged + filter + update the label. Same architecture, different dialect: and when Flutter arrives next unit, TextField's onChanged will be the SAME hook a third time. Unit 1 has 2 widgets left: image showmanship (ImageSlider, ImageSwitcher, SearchView) and then the tabbed layout that reorganises the whole app.

Summary

Key takeaways

  • AutoCompleteTextView = EditText + adapter-fed dropdown; setThreshold(n) gates when suggestions appear (minimum 1).
  • It suggests, never restricts: validate getText() when only listed values are legal.
  • TextWatcher's 3 moments: beforeTextChanged (old text), onTextChanged (new text: the live-search hook), afterTextChanged (Editable, may modify).
  • Firing order and text freshness differ: before fires first but sees the old text.
  • Watchers that edit their own text must be idempotent or they loop forever.
  • Same pattern as web live search (keyup + AJAX): one architecture, two platforms.
  • Memory hook: before sees old, on sees new, after may edit, edits must self-stop.

Study this properly

This page is the lesson to read. In Gri-Learn the same topic is a graded deck: the self-checks are scored and your weak topics are tracked. Free to start.

Start this topic

Already have an account? Sign in

More from Basic Attributes and Events of Important Android Widgets (UI)

Gri-Learn · syllabus-mapped B.C.A. lessons in English, Hindi and Gujarati

AutoCompleteTextView, TextWatcher to EditText · Mobile Application Development - 2 (option B) · Gri-Learn