TextWatcher: τι είναι, η διεπαφή TextWatcher και η υλοποίηση στο Android

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-07-08 Χρόνος ανάγνωσης: 6 λεπ

Το TextWatcher είναι μια διεπαφή Android που σας επιτρέπει να παρακολουθείτε αλλαγές κειμένου σε EditText και άλλα TextView σε πραγματικό χρόνο. Ο προγραμματιστής λαμβάνει ειδοποιήσεις σε τρία στάδια: πριν από την αλλαγή, κατά τη διάρκεια της αλλαγής και μετά την αλλαγή του περιεχομένου κειμένου. Σύμφωνα με το Android Developers, 2026, το TextWatcher χρησιμοποιείται στις περισσότερες εφαρμογές για επικύρωση εισόδου, μέτρηση χαρακτήρων, υλοποίηση αναζήτησης με autocomplete και δυναμική μορφοποίηση κειμένου. Η διεπαφή είναι απαραίτητη σε φόρμες όπου απαιτείται άμεση αντίδραση σε κάθε πάτημα πλήκτρου.

Κύρια σημεία

  • TextWatcher — ενσωματωμένη διεπαφή Android SDK για ακρόαση αλλαγών κειμένου σε TextView και EditText.
  • Η διεπαφή περιέχει τρεις μεθόδους: beforeTextChanged, onTextChanged και afterTextChanged, κάθε μία υπεύθυνη για το δικό της στάδιο αλλαγής.
  • Η μέθοδος afterTextChanged είναι πιο βολική για επικύρωση πεδίου μετά την ολοκλήρωση της εισόδου από τον χρήστη.
  • Αναδρομική κλήση — συνηθισμένο λάθος: η αλλαγή κειμένου μέσα στο TextWatcher οδηγεί σε ατελείωτο βρόχο.
  • TextWatcher χρησιμοποιείται σε πεδία αναζήτησης, επικύρωση φορμών, μέτρηση χαρακτήρων και αυτόματη μορφοποίηση αριθμού τηλεφώνου.

Τι είναι το TextWatcher και σε τι χρησιμεύει;

TextWatcher είναι μια διεπαφή από το πακέτο android.text που ειδοποιεί την εφαρμογή για αλλαγές κειμένου σε αντικείμενα Editable. Σε κάθε είσοδο, διαγραφή ή αντικατάσταση χαρακτήρα, το TextWatcher καλεί διαδοχικά τρεις μεθόδους, μεταφέροντας πληροφορίες σχετικά με τη θέση των αλλαγών. Αυτό επιτρέπει στον προγραμματιστή να αντιδρά άμεσα στις ενέργειες του χρήστη — χωρίς επιπλέον κουμπιά ή ενεργοποιητές.

Τα κύρια σενάρια χρήσης περιλαμβάνουν επικύρωση πεδίων σε πραγματικό χρόνο: έλεγχος email κατά την εισαγωγή κάθε χαρακτήρα, μέτρηση υπολοίπων χαρακτήρων σε πεδίο με όριο μήκους, υλοποίηση αναζήτησης με καθυστερημένη αποστολή αιτήματος μέσω 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 για επικύρωση πεδίων σε πραγματικό χρόνο

Η επικύρωση σε πραγματικό χρόνο βελτιώνει σημαντικά την εμπειρία χρήστη: ο χρήστης βλέπει το σφάλμα αμέσως μετά την εισαγωγή μιας λανθασμένης τιμής, όχι αφού πατήσει το κουμπί αποστολής. Το TextWatcher επιτρέπει τον άμεσο έλεγχο email, κωδικού πρόσβασης, αριθμού τηλεφώνου και άλλων πεδίων. Το αποτέλεσμα εμφανίζεται μέσω 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 για έλεγχο email. Εάν το κείμενο δεν είναι κενό και δεν ταιριάζει με το πρότυπο, ορίζεται σφάλμα στο πεδίο μέσω της ιδιότητας error. Στη σωστή εισαγωγή, το σφάλμα διαγράφεται. Είναι σημαντικό να μην εκτελείτε επικύρωση σε κενό πεδίο — ο χρήστης μπορεί να μην έχει αρχίσει ακόμη την εισαγωγή και το μήνυμα σφάλματος θα είναι πρόωρο.

Για κωδικούς πρόσβασης και αριθμούς τηλεφώνου χρησιμοποιούνται προσαρμοσμένες κανονικές εκφράσεις ή εξειδικευμένες βιβλιοθήκες. Για παράδειγμα, για τον έλεγχο πολυπλοκότητας κωδικού πρόσβασης μπορείτε να μετρήσετε τον αριθμό ψηφίων, κεφαλαίων και πεζών γραμμάτων. Το TextWatcher επιτρέπει την ενημέρωση του δείκτη πολυπλοκότητας κωδικού πρόσβασης σε πραγματικό χρόνο, το οποίο επηρεάζει θετικά τη μετατροπή εγγραφής.

Συνηθισμένα λάθη κατά την εργασία με TextWatcher

Το πρώτο και πιο κρίσιμο λάθος — αναδρομική κλήση. Εάν μέσα στο afterTextChanged αλλάξει το κείμενο του ίδιου EditText (μέσω s.clear(), s.append() ή s.insert()), το TextWatcher θα ενεργοποιηθεί ξανά. Αυτό δημιουργεί έναν ατελείωτο βρόχο που καταλήγει σε StackOverflowError. Λύση — χρήση σημαίας αποκλεισμού isUpdating ή έλεγχος εάν το κείμενο άλλαξε πραγματικά.

Το δεύτερο συνηθισμένο πρόβλημα — διαρροή μνήμης. Το TextWatcher περιέχει μια σιωπηρή αναφορά στο Activity ή Fragment μέσω μιας ανώνυμης κλάσης. Εάν ο listener δεν αφαιρεθεί κατά την καταστροφή του View, ο garbage collector δεν μπορεί να ελευθερώσει τη μνήμη. Λύση — χρήση στοιχείων κύκλου ζωής ή ρητή κλήση του removeTextChangedListener στο onDestroyView.

Το τρίτο λάθος — χρήση λανθασμένης μεθόδου. Μερικοί προγραμματιστές εκτελούν την τελική επικύρωση στο onTextChanged, χωρίς να περιμένουν το afterTextChanged. Στο onTextChanged, το κείμενο δεν έχει ακόμη ενημερωθεί πλήρως και η ανάγνωση της τελικής τιμής μπορεί να επιστρέψει λανθασμένα δεδομένα. Η σωστή προσέγγιση — τοποθέτηση όλης της λογικής ανάγνωσης και ελέγχου του τελικού κειμένου στο afterTextChanged.

ΜέθοδοςΣτιγμή κλήσηςΣκοπόςΜπορεί να διαβαστεί το τελικό κείμενο;
beforeTextChangedΠριν την αλλαγήΑποθήκευση προηγούμενης κατάστασηςΝαι
onTextChangedΚατά την αλλαγήΚαταγραφή, κινούμενα σχέδιαΌχι
afterTextChangedΜετά την αλλαγήΕπικύρωση, μέτρηση, ενημέρωση UIΝαι

Το τέταρτο λάθος — πολλαπλή προσθήκη TextWatcher. Εάν το addTextChangedListener κλήθηκε πολλές φορές για το ίδιο EditText, όλοι οι listeners θα επεξεργαστούν την ίδια αλλαγή. Σε φόρμες με δυναμική προσθήκη View, αυτό οδηγεί σε διπλασιασμό ελέγχων και απρόβλεπτη συμπεριφορά. Πάντα ελέγχετε εάν ο listener έχει ήδη προστεθεί προηγουμένως ή χρησιμοποιήστε ένα μοναδικό στιγμιότυπο.

Συχνές Ερωτήσεις

Ποια είναι η διαφορά μεταξύ onTextChanged και afterTextChanged;

To OnTextChanged καλείται τη στιγμή της αλλαγής κειμένου, όταν οι νέοι χαρακτήρες δεν έχουν ακόμη προστεθεί. Αυτή η μέθοδος είναι κατάλληλη για κινούμενα σχέδια και καταγραφή. Το AfterTextChanged καλείται μετά την πλήρη εφαρμογή των αλλαγών και παρέχει πρόσβαση στο τελικό κείμενο μέσω της παραμέτρου Editable. Για επικύρωση και ανάγνωση τιμής, χρησιμοποιήστε το afterTextChanged.

Πώς να αποφύγετε την αναδρομική κλήση του TextWatcher;

Χρησιμοποιήστε μια σημαία αποκλεισμού τύπου Boolean που ορίζεται σε true πριν από την αλλαγή κειμένου μέσα στο afterTextChanged. Στην αρχή της μεθόδου ελέγξτε τη σημαία: εάν είναι true — βγείτε. Εναλλακτικά, μπορείτε να συγκρίνετε την παλιά και τη νέα τιμή και να αλλάξετε το κείμενο μόνο όταν υπάρχει πραγματική διαφορά.

Πρέπει να αφαιρείται το TextWatcher κατά την καταστροφή του Activity;

Ναι, υποχρεωτικά. Η ανώνυμη κλάση του TextWatcher διατηρεί μια αναφορά στο Activity μέσω του closure. Εάν ο listener δεν αφαιρεθεί, το Activity δεν μπορεί να συλλεχθεί από τον garbage collector. Πάντα καλείτε το removeTextChangedListener στο onDestroyView για Fragment ή στο onDestroy για Activity.

Μπορεί να χρησιμοποιηθεί το TextWatcher σε RecyclerView;

Ναι, αλλά με προσοχή. Στο RecyclerView, τα ViewHolder επαναχρησιμοποιούνται και το TextWatcher από την προηγούμενη θέση μπορεί να παραμείνει ενεργό. Πάντα αφαιρείτε το παλιό TextWatcher πριν ορίσετε ένα νέο στη μέθοδο onBindViewHolder. Χρησιμοποιήστε tags ή ξεχωριστά πεδία ViewHolder για αποθήκευση αναφοράς στον listener.

Ποια μέθοδος είναι καλύτερη για αναζήτηση με autocomplete;

Για το πεδίο αναζήτησης χρησιμοποιήστε το afterTextChanged σε συνδυασμό με debounce (καθυστέρηση). Εφαρμόστε ένα χρονόμετρο 300-500 ms που γίνεται reset σε κάθε νέα αλλαγή κειμένου. Αυτό αποτρέπει την αποστολή αιτήματος στον διακομιστή σε κάθε πάτημα πλήκτρου και μειώνει το φορτίο του API.

Σύνοψη

  • TextWatcher — διεπαφή Android για παρακολούθηση αλλαγών κειμένου σε EditText και TextView, που υλοποιεί τρεις μεθόδους επιστροφής κλήσης.
  • Η μέθοδος afterTextChanged — βέλτιστη επιλογή για επικύρωση και ανάγνωση του τελικού κειμένου μετά από αλλαγές.
  • Αναδρομική κλήση — ο κύριος κίνδυνος του TextWatcher, αποτρέπεται με σημαία αποκλεισμού.
  • Αφαίρεση του listener είναι υποχρεωτική για αποτροπή διαρροής μνήμης κατά την καταστροφή Activity ή Fragment.
  • Επικύρωση σε πραγματικό χρόνο με TextWatcher βελτιώνει την εμπειρία χρήστη και επιτρέπει την άμεση εμφάνιση σφαλμάτων.
  • Debounce είναι απαραίτητο κατά την υλοποίηση αναζήτησης και autocomplete για μείωση φορτίου διακομιστή.
  • Σωστή επιλογή μεθόδου — το κλειδί για σταθερή λειτουργία: beforeTextChanged για αποθήκευση κατάστασης, onTextChanged για καταγραφές, afterTextChanged για τελικό έλεγχο.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης