TextWatcher: шта је то, интерфејс TextWatcher и имплементација у Android-у

Аутор: IT Sectr Објављено: 2026-07-08 Време читања: 6 мин

TextWatcher је Android интерфејс који омогућава праћење промена текста у EditText и другим TextView у реалном времену. Програмер добија обавештења у три фазе: пре промене, током промене и после промене текстуалног садржаја. Према Android Developers, 2026, TextWatcher се примењује у већини апликација за валидацију уноса, бројање знакова, имплементацију претраге са аутоматским допуњавањем и динамичко форматирање текста. Интерфејс је незаменљив у формама где је потребна тренутна реакција на сваки притисак тастера.

Главно

  • TextWatcher — уграђени интерфејс Android SDK за ослушкивање промена текста у TextView и EditText.
  • Интерфејс садржи три методе: beforeTextChanged, onTextChanged и afterTextChanged, свака одговара за своју фазу промене.
  • Метода afterTextChanged је најпогоднија за валидацију поља након завршетка уноса од стране корисника.
  • Рекурзивни позив — честа грешка: промена текста унутар TextWatcher-а доводи до бесконачне петље.
  • TextWatcher се примењује у пољима за претрагу, валидацији форми, бројању знакова и аутоматском форматирању броја телефона.

Шта је TextWatcher и зашто је потребан?

TextWatcher — интерфејс из пакета android.text који обавештава апликацију о променама текста у Editable објектима. При сваком уносу, брисању или замени знака, TextWatcher секвенцијално позива три методе, преносећи информације о положају промена. Ово омогућава програмеру да реагује на радње корисника тренутно — без додатних дугмади или окидача.

Главни сценарији употребе укључују валидацију поља у реалном времену: провера е-поште при уносу сваког знака, бројање преосталих знакова у пољу са ограничењима дужине, имплементација претраге са одложеним слањем захтева путем debounce-а. Такође, TextWatcher се користи за форматирање уноса — на пример, аутоматско постављање размака у броју телефона или додавање маске за датум.

Према Android Developers, TextWatcher је присутан у 70% апликација које раде са формама. Библиотеке попут Material Design Components и TextInputEditText користе TextWatcher интерно за управљање стањем грешке и приказ бројача. Разумевање рада овог интерфејса је неопходно за сваког Android програмера.

Како ради интерфејс TextWatcher

TextWatcher се повезује на било који TextView или EditText објекат преко методе addTextChangedListener. Када корисник уноси или брише знак, Android прво позива beforeTextChanged, затим onTextChanged и на крају afterTextChanged. У параметрима сваке методе преносе се подаци о измењеном опсегу: почетна позиција, број избрисаних знакова и број додатих знакова.

Важно је разумети да након позива afterTextChanged објекат Editable већ садржи актуелну вредност. Зато је у afterTextChanged згодно проверавати коначни текст поља. До тог тренутка подаци још нису у потпуности ажурирани. Програмери често мешају намену метода и користе onTextChanged за коначну валидацију, иако је прави избор afterTextChanged.

Посебности позивања метода

При сваком уметању, замени или брисању знака ланац позива се гарантовано извршава у потпуности. Међутим, ако се унутар afterTextChanged промени текст (путем clear, append, insert), TextWatcher ће се покренути рекурзивно. Ово је најчешћи узрок StackOverflowError-а у Android формама. За спречавање рекурзије користи се закључавајући флаг.

Три методе TextWatcher-а: beforeTextChanged, onTextChanged, afterTextChanged

Свака од три методе има своју улогу у животном циклусу промене текста. Метода beforeTextChanged(CharSequence s, int start, int count, int after) се позива пре примене промена. Она преноси тренутно стање ниске, почетну позицију промене, број знакова који се бришу и број знакова који се додају. Овде се може сачувати претходна вредност или проверити услови пре модификације.

Метода onTextChanged се позива током промене, када су знакови већ избрисани, али нови још нису уметнути. Параметри: текст након брисања, почетна позиција, број избрисаних знакова и број знакова који се додају. Ова метода је погодна за анимацију или логирање, али не за рад са актуелним коначним текстом — он још није састављен.

Метода afterTextChanged је најтраженија. Она прима Editable објекат и позива се након што су промене у потпуности примењене. У овој методи се може читати коначна вредност поља, вршити валидација, ажурирати UI и мењати текст (уз опрез због рекурзије).

Пример имплементације TextWatcher-а за бројање знакова

Практичан пример — бројач знакова за поље уноса који се ажурира при свакој промени текста. Такав елемент се често среће у формама за контакт, објавама и порукама са ограничењем дужине. Имплементација путем TextWatcher-а захтева неколико линија и не захтева библиотеке трећих страна.

kotlin
val editText = findViewById<EditText>(R.id.edit_text)
val counterText = findViewById<TextView>(R.id.counter)

editText.addTextChangedListener(object : TextWatcher {
    override fun beforeTextChanged(
        s: CharSequence?, start: Int,
        count: Int, after: Int
    ) {}

    override fun onTextChanged(
        s: CharSequence?, start: Int,
        before: Int, count: Int
    ) {}

    override fun afterTextChanged(s: Editable?) {
        val len = s?.length ?: 0
        counterText.text = "$len / 200"
    }
})

У примеру, метода afterTextChanged добија тренутни садржај поља преко параметра s типа Editable. Дужина текста се ажурира у засебном TextView-у. Да би се избегла рекурзија у овом случају, мења се само counterText, а не сам EditText, тако да петља не настаје. При лимиту од 200 знакова може се додатно блокирати унос након прекорачења.

Методе beforeTextChanged и onTextChanged остају празне, јер је за бројање дужине довољно коначно стање. Ако је потребно логирати сваку промену, код се може додати у onTextChanged. Таква флексибилност чини TextWatcher универзалним алатом за све сценарије рада са текстуалним уносом.

TextWatcher за валидацију поља у реалном времену

Валидација у реалном времену значајно побољшава UX: корисник види грешку одмах након уноса неисправне вредности, а не након притиска на дугме за слање. TextWatcher омогућава тренутну проверу е-поште, лозинке, броја телефона и других поља. Резултат се приказује путем setError на EditText-у или кроз засебан TextView са поруком о грешци.

kotlin
fun validateEmail(emailEditText: EditText) {
    emailEditText.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            val email = s?.toString () ?: ""
            if (email.isNotBlank() &&
                !Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
                emailEditText.error = "Invalid email address"
            } else {
                emailEditText.error = null
            }
        }

        override fun beforeTextChanged(...) {}
        override fun onTextChanged(...) {}
    })
}

У примеру се користи уграђени Patterns.EMAIL_ADDRESS из Android SDK-а за проверу е-поште. Ако текст није празан и не одговара шаблону, пољу се поставља грешка преко својства error. При исправном уносу грешка се брише. Важно је не покретати валидацију на празном пољу — корисник можда још није почео унос, а порука о грешци би била преурањена.

За лозинке и бројеве телефона користе се прилагођени регуларни изрази или специјализоване библиотеке. На пример, за проверу сложености лозинке може се избројати број цифара, великих и малих слова. TextWatcher омогућава ажурирање индикатора сложености лозинке у реалном времену, што позитивно утиче на конверзију регистрације.

Типичне грешке при раду са TextWatcher-ом

Прва и најкритичнија грешка — рекурзивни позив. Ако се унутар afterTextChanged промени текст истог EditText-а (путем s.clear(), s.append() или s.insert()), TextWatcher ће се поново покренути. Ово ствара бесконачну петљу која се завршава StackOverflowError-ом. Решење — коришћење закључавајућег флага isUpdating или провера да ли се текст стварно променио.

Други чест проблем — цурење меморије. TextWatcher садржи имплицитну референцу на Activity или Fragment преко анонимне класе. Ако се listener не уклони при уништењу View-а, сакупљач отпада не може да ослободи меморију. Решење — коришћење компоненти животног циклуса или експлицитно позивање removeTextChangedListener у onDestroyView.

Трећа грешка — коришћење погрешне методе. Неки програмери врше коначну валидацију у onTextChanged, не чекајући afterTextChanged. У onTextChanged текст још није у потпуности ажуриран и читање коначне вредности може вратити неисправне податке. Правилан приступ — постављање целокупне логике читања и провере коначног текста у afterTextChanged.

МетодаТренутак позиваНаменаМоже се читати коначни текст?
beforeTextChangedПре променеЧување претходног стањаДа
onTextChangedТоком променеЛогирање, анимацијаНе
afterTextChangedПосле променеВалидација, бројање, ажурирање UIДа

Четврта грешка — вишеструко додавање TextWatcher-а. Ако је addTextChangedListener позван више пута за један EditText, сви listener-и ће обрађивати исту промену. У формама са динамичким додавањем View-а, ово доводи до дуплирања провера и непредвидивог понашања. Увек проверавајте да ли је listener већ додат или користите јединствену инстанцу.

Често постављана питања

Чиме се разликује onTextChanged од afterTextChanged?

OnTextChanged се позива у тренутку промене текста, када нови знакови још нису додати. Ова метода је погодна за анимацију и логирање. AfterTextChanged се позива након потпуне примене промена и даје приступ коначном тексту кроз Editable параметар. За валидацију и читање вредности користите afterTextChanged.

Како избећи рекурзивни позив TextWatcher-а?

Користите закључавајући флаг типа Boolean који се поставља на true пре промене текста унутар afterTextChanged. На почетку методе проверавајте флаг: ако је true — изађите. Алтернативно, можете упоредити стару и нову вредност и мењати текст само при стварном одступању.

Да ли треба уклонити TextWatcher при уништењу Activity-ја?

Да, обавезно. Анонимна класа TextWatcher-а задржава референцу на Activity преко затварања. Ако listener није уклоњен, Activity не може да буде прикупљен од стране сакупљача отпада. Увек позивајте removeTextChangedListener у onDestroyView за Fragment или onDestroy за Activity.

Може ли се TextWatcher користити у RecyclerView-у?

Да, али са опрезом. У RecyclerView-у се ViewHolder-и поново користе и TextWatcher са претходне позиције може остати активан. Увек уклањајте стари TextWatcher пре постављања новог у методи onBindViewHolder. Користите ознаке или засебна поља ViewHolder-а за чување референце на listener.

Која метода је најбоља за претрагу са аутоматским допуњавањем?

За поље за претрагу користите afterTextChanged у комбинацији са debounce-ом (кашњењем). Имплементирајте тајмер од 300-500 ms који се ресетује при свакој новој промени текста. Ово спречава слање захтева на сервер при сваком притиску тастера и смањује оптерећење API-ја.

Резиме

  • TextWatcher — Android интерфејс за праћење промена текста у EditText и TextView, који имплементира три методе повратног позива.
  • Метода afterTextChanged — оптималан избор за валидацију и читање коначног текста након промена.
  • Рекурзивни позив — главна опасност TextWatcher-а, спречава се закључавајућим флагом.
  • Уклањање listener-а је обавезно за спречавање цурења меморије при уништењу Activity-ја или Fragment-а.
  • Валидација у реалном времену са TextWatcher-ом побољшава UX и омогућава тренутно приказивање грешака.
  • Debounce је неопходан при имплементацији претраге и аутоматског допуњавања за смањење оптерећења сервера.
  • Правилан избор методе — кључ за стабилан рад: beforeTextChanged за чување стања, onTextChanged за логове, afterTextChanged за коначну проверу.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође