TextWatcher একটি Android ইন্টারফেস যা রিয়েল টাইমে EditText এবং অন্যান্য TextView-এ টেক্সট পরিবর্তন ট্র্যাক করতে দেয়। ডেভেলপার তিনটি ধাপে বিজ্ঞপ্তি পায়: পরিবর্তনের আগে, পরিবর্তনের সময়, এবং টেক্সট বিষয়বস্তু পরিবর্তনের পরে। Android Developers, 2026 অনুসারে, TextWatcher বেশিরভাগ অ্যাপ্লিকেশনে ইনপুট যাচাইকরণ, অক্ষর গণনা, অটোকমপ্লিট সহ অনুসন্ধান বাস্তবায়ন এবং ডায়নামিক টেক্সট ফরম্যাটিংয়ের জন্য ব্যবহৃত হয়। ইন্টারফেসটি এমন ফর্মগুলিতে অপরিহার্য যেখানে প্রতিটি কী প্রেসে তাৎক্ষণিক প্রতিক্রিয়া প্রয়োজন।
মূল পয়েন্ট
TextWatcher android.text প্যাকেজের একটি ইন্টারফেস যা Editable অবজেক্টে টেক্সট পরিবর্তন সম্পর্কে অ্যাপ্লিকেশনকে জানায়। প্রতিটি ইনপুট, মুছে ফেলা বা অক্ষর প্রতিস্থাপনের সাথে, TextWatcher ক্রমান্বয়ে তিনটি পদ্ধতি কল করে, পরিবর্তনের অবস্থান সম্পর্কে তথ্য প্রেরণ করে। এটি ডেভেলপারকে অতিরিক্ত বোতাম বা ট্রিগার ছাড়াই তাত্ক্ষণিকভাবে ব্যবহারকারীর ক্রিয়াকলাপে প্রতিক্রিয়া জানাতে দেয়।
প্রধান ব্যবহারের ক্ষেত্রে রিয়েল টাইম ফিল্ড যাচাইকরণ অন্তর্ভুক্ত: প্রতিটি অক্ষর টাইপ করার সময় ইমেল পরীক্ষা করা, দৈর্ঘ্য সীমা সহ একটি ফিল্ডে অবশিষ্ট অক্ষর গণনা করা, ডিবাউন্সের মাধ্যমে বিলম্বিত অনুরোধ সহ অনুসন্ধান বাস্তবায়ন করা। TextWatcher ইনপুট ফরম্যাটিংয়ের জন্যও ব্যবহৃত হয় — যেমন, ফোন নম্বরে স্বয়ংক্রিয়ভাবে স্পেস যোগ করা বা তারিখের জন্য মাস্ক যোগ করা।
Android Developers অনুসারে, TextWatcher ফর্ম নিয়ে কাজ করে এমন 70% অ্যাপ্লিকেশনে উপস্থিত। Material Design Components এবং TextInputEditText-এর মতো লাইব্রেরিগুলি ত্রুটি অবস্থা পরিচালনা এবং কাউন্টার প্রদর্শনের জন্য অভ্যন্তরীণভাবে TextWatcher ব্যবহার করে। এই ইন্টারফেসের কাজ বোঝা প্রতিটি Android ডেভেলপারের জন্য প্রয়োজনীয়।
TextWatcher addTextChangedListener পদ্ধতির মাধ্যমে যেকোনো TextView বা EditText অবজেক্টের সাথে সংযুক্ত হয়। যখন ব্যবহারকারী একটি অক্ষর টাইপ বা মুছে ফেলে, Android প্রথমে beforeTextChanged, তারপর onTextChanged, এবং শেষে afterTextChanged কল করে। প্রতিটি পদ্ধতির প্যারামিটারে পরিবর্তিত পরিসর সম্পর্কে ডেটা থাকে: শুরু অবস্থান, মুছে ফেলা অক্ষরের সংখ্যা এবং যোগ করা অক্ষরের সংখ্যা।
এটা বোঝা গুরুত্বপূর্ণ যে afterTextChanged কল করার পরে, Editable অবজেক্টে ইতিমধ্যে বর্তমান মান থাকে। তাই, afterTextChanged-এ ফিল্ডের চূড়ান্ত টেক্সট পরীক্ষা করা সুবিধাজনক। সেই মুহুর্তের আগে, ডেটা এখনও সম্পূর্ণরূপে আপডেট হয়নি। ডেভেলপাররা প্রায়ই পদ্ধতিগুলির উদ্দেশ্য নিয়ে বিভ্রান্ত হন এবং চূড়ান্ত যাচাইকরণের জন্য onTextChanged ব্যবহার করেন, যদিও সঠিক পছন্দ হল afterTextChanged।
প্রতিটি অক্ষর সন্নিবেশ, প্রতিস্থাপন বা মুছে ফেলার সাথে, কল চেইন সম্পূর্ণরূপে নির্বাহিত হওয়ার নিশ্চয়তা রয়েছে। তবে, afterTextChanged-এর ভিতরে টেক্সট পরিবর্তন করা হলে (clear, append, insert-এর মাধ্যমে), TextWatcher পুনরাবৃত্তভাবে সক্রিয় হবে। এটি Android ফর্মে StackOverflowError-এর সবচেয়ে সাধারণ কারণ। পুনরাবৃত্তি রোধ করতে ফ্ল্যাগ-লক ব্যবহার করা হয়।
তিনটি পদ্ধতির প্রতিটি টেক্সট পরিবর্তনের জীবনচক্রে নিজস্ব ভূমিকা পালন করে। beforeTextChanged(CharSequence s, int start, int count, int after) পদ্ধতি পরিবর্তন প্রয়োগের আগে কল করা হয়। এটি স্ট্রিংয়ের বর্তমান অবস্থা, পরিবর্তনের শুরু অবস্থান, মুছে ফেলা অক্ষরের সংখ্যা এবং যোগ করা অক্ষরের সংখ্যা প্রেরণ করে। এখানে আপনি পরিবর্তনের আগে পূর্বের মান সংরক্ষণ করতে পারেন বা শর্ত পরীক্ষা করতে পারেন।
onTextChanged পদ্ধতি পরিবর্তনের সময় কল করা হয়, যখন অক্ষরগুলি ইতিমধ্যে মুছে ফেলা হয়েছে কিন্তু নতুনগুলি এখনও সন্নিবেশ করা হয়নি। প্যারামিটার: মুছে ফেলার পরে টেক্সট, শুরু অবস্থান, মুছে ফেলা অক্ষরের সংখ্যা এবং যোগ করা অক্ষরের সংখ্যা। এই পদ্ধতিটি অ্যানিমেশন বা লগিংয়ের জন্য সুবিধাজনক, তবে প্রকৃত চূড়ান্ত টেক্সট নিয়ে কাজ করার জন্য নয় — এটি এখনও একত্রিত হয়নি।
afterTextChanged পদ্ধতি সবচেয়ে বেশি চাহিদাযুক্ত। এটি একটি Editable অবজেক্ট গ্রহণ করে এবং পরিবর্তনগুলি সম্পূর্ণরূপে প্রয়োগ হওয়ার পরে কল করা হয়। এই পদ্ধতিতে আপনি ফিল্ডের চূড়ান্ত মান পড়তে পারেন, যাচাইকরণ করতে পারেন, UI আপডেট করতে পারেন এবং টেক্সট পরিবর্তন করতে পারেন (পুনরাবৃত্তির কারণে সতর্কতার সাথে)।
একটি ব্যবহারিক উদাহরণ — একটি ইনপুট ফিল্ডের জন্য অক্ষর কাউন্টার যা প্রতিটি টেক্সট পরিবর্তনের সাথে আপডেট হয়। এই ধরনের উপাদান প্রায়ই প্রতিক্রিয়া ফর্ম, পোস্ট এবং দৈর্ঘ্য সীমা সহ বার্তাগুলিতে পাওয়া যায়। TextWatcher-এর মাধ্যমে বাস্তবায়নে কয়েকটি লাইন লাগে এবং তৃতীয়-পক্ষের লাইব্রেরির প্রয়োজন হয় না।
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 পদ্ধতি Editable টাইপের s প্যারামিটারের মাধ্যমে ফিল্ডের বর্তমান বিষয়বস্তু গ্রহণ করে। টেক্সটের দৈর্ঘ্য একটি আলাদা TextView-তে আপডেট করা হয়। এই ক্ষেত্রে, শুধুমাত্র counterText পরিবর্তিত হয়, EditText নিজেই নয়, তাই কোনো লুপ তৈরি হয় না। 200 অক্ষরের সীমার জন্য, অতিক্রম করার পরে ইনপুট অতিরিক্তভাবে ব্লক করা যেতে পারে।
beforeTextChanged এবং onTextChanged পদ্ধতি খালি থাকে, কারণ দৈর্ঘ্য গণনার জন্য চূড়ান্ত অবস্থা যথেষ্ট। যদি প্রতিটি পরিবর্তন লগ করার প্রয়োজন হয়, onTextChanged-এ কোড যোগ করা যেতে পারে। এই ধরনের নমনীয়তা TextWatcher-কে টেক্সট ইনপুট সহ যেকোনো দৃশ্যের জন্য একটি সার্বজনীন টুল করে তোলে।
রিয়েল টাইম যাচাইকরণ UX-এ উল্লেখযোগ্যভাবে উন্নতি করে: ব্যবহারকারী সাবমিট বাটন ক্লিক করার পরে নয়, বরং ভুল মান 입력 করার সাথে সাথেই ত্রুটি দেখতে পায়। TextWatcher ইমেল, পাসওয়ার্ড, ফোন নম্বর এবং অন্যান্য ফিল্ডের তাৎক্ষণিক পরীক্ষার অনুমতি দেয়। ফলাফল EditText-এ setError-এর মাধ্যমে বা ত্রুটি বার্তা সহ আলাদা TextView-এর মাধ্যমে প্রদর্শিত হয়।
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(...) {}
})
}
উদাহরণটি ইমেল পরীক্ষা করার জন্য Android SDK থেকে বিল্ট-ইন Patterns.EMAIL_ADDRESS ব্যবহার করে। যদি টেক্সট খালি না হয় এবং প্যাটার্নের সাথে মেলে না, তবে error প্রপার্টির মাধ্যমে ফিল্ডে ত্রুটি সেট করা হয়। সঠিক ইনপুটে ত্রুটি পরিষ্কার হয়ে যায়। খালি ফিল্ডে যাচাইকরণ না চালানো গুরুত্বপূর্ণ — ব্যবহারকারী এখনও টাইপ করা শুরু না করতে পারে, এবং ত্রুটি বার্তা অকালপক্ব হবে।
পাসওয়ার্ড এবং ফোন নম্বরের জন্য, কাস্টম রেগুলার এক্সপ্রেশন বা বিশেষায়িত লাইব্রেরি ব্যবহার করা হয়। উদাহরণস্বরূপ, পাসওয়ার্ড জটিলতা পরীক্ষা করার জন্য অঙ্ক, বড় এবং ছোট হাতের অক্ষরের সংখ্যা গণনা করা যেতে পারে। TextWatcher রিয়েল টাইমে পাসওয়ার্ড শক্তি নির্দেশক আপডেট করার অনুমতি দেয়, যা নিবন্ধন রূপান্তরকে ইতিবাচকভাবে প্রভাবিত করে।
প্রথম এবং সবচেয়ে গুরুতর ভুল হল পুনরাবৃত্ত কল। যদি afterTextChanged-এর ভিতরে একই EditText-এর টেক্সট পরিবর্তন করা হয় (s.clear(), s.append() বা s.insert()-এর মাধ্যমে), TextWatcher আবার সক্রিয় হবে। এটি একটি অসীম লুপ তৈরি করে যা StackOverflowError-এ শেষ হয়। সমাধান হল isUpdating ফ্ল্যাগ-লক ব্যবহার করা বা টেক্সট আসলে পরিবর্তিত হয়েছে কিনা তা পরীক্ষা করা।
দ্বিতীয় সাধারণ সমস্যা হল মেমরি লিক। TextWatcher একটি anonymous class-এর মাধ্যমে Activity বা Fragment-এর অন্তর্নিহিত রেফারেন্স ধারণ করে। View ধ্বংস হলে listener সরানো না হলে, garbage collector মেমরি মুক্ত করতে পারে না। সমাধান হল lifecycle কম্পোনেন্ট ব্যবহার করা বা onDestroyView-এ স্পষ্টভাবে removeTextChangedListener কল করা।
তৃতীয় ভুল হল ভুল পদ্ধতি ব্যবহার করা। কিছু ডেভেলপার afterTextChanged-এর জন্য অপেক্ষা না করে onTextChanged-এ চূড়ান্ত যাচাইকরণ করে। onTextChanged-এ, টেক্সট এখনও সম্পূর্ণরূপে আপডেট হয়নি, এবং চূড়ান্ত মান পড়লে ভুল ডেটা ফিরে আসতে পারে। সঠিক পদ্ধতি হল চূড়ান্ত টেক্সট পড়ার এবং পরীক্ষা করার সমস্ত যুক্তি afterTextChanged-এ থাকা উচিত।
| পদ্ধতি | কলের সময় | উদ্দেশ্য | চূড়ান্ত টেক্সট পড়া যায়? |
|---|---|---|---|
| beforeTextChanged | পরিবর্তনের আগে | পূর্ববর্তী অবস্থা সংরক্ষণ | হ্যাঁ |
| onTextChanged | পরিবর্তনের সময় | লগিং, অ্যানিমেশন | না |
| afterTextChanged | পরিবর্তনের পরে | যাচাইকরণ, গণনা, UI আপডেট | হ্যাঁ |
চতুর্থ ভুল হল একাধিক TextWatcher যোগ করা। যদি একই EditText-এর জন্য addTextChangedListener একাধিকবার কল করা হয়, তাহলে সব listener একই পরিবর্তন প্রক্রিয়া করবে। ডায়নামিক View যোগ সহ ফর্মগুলিতে, এটি ডুপ্লিকেট পরীক্ষা এবং অপ্রত্যাশিত আচরণের দিকে নিয়ে যায়। সবসময় পরীক্ষা করুন যে listener আগে যোগ করা হয়েছে কিনা, অথবা একটি একক ইনস্ট্যান্স ব্যবহার করুন।
সচরাচর জিজ্ঞাসিত প্রশ্ন
OnTextChanged টেক্সট পরিবর্তনের মুহূর্তে কল করা হয় যখন নতুন অক্ষর এখনও যোগ করা হয়নি। এই পদ্ধতিটি অ্যানিমেশন এবং লগিংয়ের জন্য উপযুক্ত। AfterTextChanged পরিবর্তন সম্পূর্ণরূপে প্রয়োগ হওয়ার পরে কল করা হয় এবং Editable প্যারামিটারের মাধ্যমে চূড়ান্ত টেক্সটে অ্যাক্সেস দেয়। যাচাইকরণ এবং মান পড়ার জন্য afterTextChanged ব্যবহার করুন।
Boolean টাইপের একটি ফ্ল্যাগ-লক ব্যবহার করুন, যা afterTextChanged-এর ভিতরে টেক্সট পরিবর্তনের আগে true-তে সেট হয়। পদ্ধতির শুরুতে ফ্ল্যাগ পরীক্ষা করুন: যদি true হয় — বেরিয়ে আসুন। বিকল্পভাবে, পুরানো এবং নতুন মান তুলনা করুন এবং শুধুমাত্র প্রকৃত পার্থক্য থাকলে টেক্সট পরিবর্তন করুন।
হ্যাঁ, অবশ্যই. Anonymous TextWatcher ক্লাস ক্লোজারের মাধ্যমে Activity-র রেফারেন্স ধারণ করে। যদি listener সরানো না হয়, Activity garbage collector দ্বারা সংগ্রহ করা যাবে না। Fragment-এর জন্য onDestroyView বা Activity-র জন্য onDestroy-এ সর্বদা removeTextChangedListener কল করুন।
হ্যাঁ, তবে সতর্কতার সাথে। RecyclerView-এ, ViewHolders পুনরায় ব্যবহার করা হয় এবং পূর্ববর্তী অবস্থানের TextWatcher সক্রিয় থাকতে পারে। onBindViewHolder পদ্ধতিতে নতুন সেট করার আগে সর্বদা পুরানো TextWatcher সরান। listener-এর রেফারেন্স সংরক্ষণের জন্য ট্যাগ বা ViewHolder-এর আলাদা ফিল্ড ব্যবহার করুন।
অনুসন্ধান ফিল্ডের জন্য, ডিবাউন্স (বিলম্ব) সহ afterTextChanged ব্যবহার করুন। 300-500 ms-এর একটি টাইমার প্রয়োগ করুন যা প্রতিটি নতুন টেক্সট পরিবর্তনে রিসেট হয়। এটি প্রতিটি কী প্রেসে সার্ভারে অনুরোধ পাঠানো প্রতিরোধ করে এবং API লোড হ্রাস করে।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন