Hilt-এর উন্নত ব্যবহার: @Qualifier এবং @Bind অ্যানোটেশন

  • ডিপেন্ডেন্সি ম্যানেজমেন্টের জন্য @Binds এবং @Provides অ্যানোটেশনের মধ্যে প্রধান পার্থক্য ও ব্যবহার।
  • Hilt ডিপেন্ডেন্সি গ্রাফে অভিন্ন টাইপের দ্বন্দ্ব নিরসনের জন্য @Qualifier প্রয়োগ করা হচ্ছে।
  • @Singleton এবং @ViewModelScoped-এর মতো স্কোপ ব্যবহারের মাধ্যমে উন্নত লাইফসাইকেল ম্যানেজমেন্ট।
  • @EntryPoint ব্যবহার করে অসমর্থিত ক্লাসগুলিতে ডিপেন্ডেন্সি ইনজেকশন একীভূত করার কৌশল।

Hilt-এর উন্নত ব্যবহার: @Qualifier এবং @Bind অ্যানোটেশন

আপনার অ্যান্ড্রয়েড অ্যাপের কোড যদি কখনো পুরোপুরি এলোমেলো হয়ে যাচ্ছে বলে মনে হয়, যেখানে ইনস্ট্যান্সগুলো এক ক্লাস থেকে অন্য ক্লাসে যেন গরম আলুর মতো পাস করা হচ্ছে, তাহলে সম্ভবত আপনি ‘ ডিপেন্ডেন্সি হেল’-এর ফাঁদে পড়েছেন । আপনার প্রজেক্টকে নিয়ন্ত্রণহীন হয়ে পড়া থেকে বাঁচাতে, গুগল ড্যাগার হিল্ট (Dagger Hilt) নিয়ে এসেছে। এটি এমন একটি টুল যা সমস্ত কঠিন কাজ করে দেয় এবং আপনার ক্লাসগুলোর প্রয়োজনীয় অবজেক্টগুলো স্বয়ংক্রিয়ভাবে পৌঁছে দেয়, ফলে আপনাকে বিরক্ত না হওয়া পর্যন্ত একই কোড বারবার লিখতে হয় না।

প্রচলিত ড্যাগার (Dagger)-এর মতো নয়, যা শেখা বেশ কঠিন হওয়ায় মাঝে মাঝে ভীতিজনক মনে হতে পারে, হিল্ট (Hilt) অনেক বেশি মানসম্মত এবং সহজবোধ্য একটি পদ্ধতি প্রদান করে। এটি জেটপ্যাক কম্পোজ (Jetpack Compose) এবং আধুনিক আর্কিটেকচারের সাথে নির্বিঘ্নে কাজ করে , রানটাইম পারফরম্যান্স অপ্টিমাইজ করে এবং নিশ্চিত করে যে আপনি কোনো অপ্রীতিকর পরিস্থিতির সম্মুখীন হবেন না, যেমন কোনো ডিপেন্ডেন্সি অনুপস্থিত থাকার ত্রুটি, কারণ কম্পাইলেশনের সময় সবকিছু যাচাই করা হয়।

প্রাথমিক কনফিগারেশন এবং সিস্টেম চালু করা

Hilt ব্যবহার শুরু করার জন্য, প্রথম ধাপ হলো আপনার Gradle এনভায়রনমেন্ট সেট আপ করা। রুট ফাইলে hilt-android-gradle-plugin যোগ করা এবং তারপর আপনার অ্যাপ্লিকেশন মডিউলে ডিপেন্ডেন্সিগুলো প্রয়োগ করা অত্যন্ত গুরুত্বপূর্ণ। এখানে একটি গুরুত্বপূর্ণ বিষয় হলো, আপনার প্রজেক্টটি অবশ্যই Java 17- এর জন্য কনফিগার করা থাকতে হবে ; অন্যথায়, Hilt এবং Compose-এর বর্তমান সংস্করণগুলো গুরুতর সমস্যা সৃষ্টি করতে পারে।

এই জাদু শুরু হওয়ার জন্য, যে কোনো অ্যাপ যা এই সিস্টেমটি ব্যবহার করতে চায়, সেটিতে অবশ্যই @HiltAndroidApp অ্যানোটেশন দ্বারা চিহ্নিত একটি Application ক্লাস থাকতে হবে । এই ট্যাগটি হলো সেই সুইচ যা কোড জেনারেশন সক্রিয় করে এবং সেই ভিত্তি তৈরি করে যেখানে সম্পূর্ণ অবজেক্ট গ্রাফটি থাকবে; এটি ছাড়া, Hilt-এর নিজেকে নোঙর করার কোনো জায়গা থাকবে না এবং আপনার কোনো কাজই হবে না।

অ্যান্ড্রয়েড কম্পোনেন্টগুলিতে ডিপেন্ডেন্সি ইনজেক্ট করা

একবার ভিত্তি তৈরি হয়ে গেলে, আমাদের Hilt-কে জানাতে হবে যে আমরা কোন ক্লাসগুলিতে অবজেক্টগুলি গ্রহণ করতে চাই। আমরা `@AndroidEntryPoint` ব্যবহার করে এটি করি , যা ফ্রেমওয়ার্কের বেশিরভাগ অংশের সাথে সামঞ্জস্যপূর্ণ, যেমন অ্যাক্টিভিটি, সার্ভিস এবং ব্রডকাস্টরিসিভার। আপনি যদি কম্পোজ ব্যবহার করেন, তবে কেবল রুট অ্যাক্টিভিটিকে অ্যানোটেট করুন, এবং সমস্ত কম্পোজেবল এলিমেন্ট কোনো সমস্যা ছাড়াই ইনজেক্টেড ভিউমডেলগুলি অ্যাক্সেস করতে পারবে।

কোনো অ্যাক্টিভিটির কোডে সরাসরি একটি অবজেক্ট যুক্ত করতে, আমরা `@Inject` সহ ফিল্ড ইনজেকশন ব্যবহার করি । এর জন্য শুধু ভেরিয়েবলটিকে `lateinit var` হিসেবে সংজ্ঞায়িত করুন এবং অ্যানোটেশনটি যোগ করুন। তবে, খুব সতর্ক থাকুন: ইনজেক্টেড ফিল্ডগুলো প্রাইভেট হতে পারে না , কারণ ইনস্ট্যান্স অ্যাসাইন করার জন্য Hilt-এর সেগুলোতে অ্যাক্সেস প্রয়োজন হয়; যদি আপনি সেগুলোকে প্রাইভেট করার চেষ্টা করেন, তাহলে কম্পাইলার সাথে সাথে একটি এরর দেখাবে।

এমভিভিএম
সম্পর্কিত নিবন্ধ:
MVVM: আধুনিক অ্যাপের জন্য চূড়ান্ত সফ্টওয়্যার আর্কিটেকচার প্যাটার্ন

সংযোগ স্থাপনের কলাকৌশল: @Binds বনাম @Provides

আমরা হিল্টকে যা কিছু তৈরি করতে বলি, তার প্রতিটি কীভাবে তৈরি করতে হয় তা তার জানা প্রয়োজন। এর সবচেয়ে সহজ উপায় হলো কনস্ট্রাক্টর ইনজেকশন, যেখানে আমরা ক্লাস কনস্ট্রাক্টরকে `@Inject` দিয়ে অ্যানোটেট করি। কিন্তু এমন কিছু ক্ষেত্র আছে যেখানে এটি করা অসম্ভব, যেমন ইন্টারফেস বা রেট্রোফিট বা রুমের মতো এক্সটার্নাল লাইব্রেরি নিয়ে কাজ করার সময়, যেখানে অ্যানোটেশন যোগ করার জন্য আমরা সোর্স কোড পরিবর্তন করতে পারি না।

এখানেই মডিউলের ভূমিকা আসে, যেগুলো হলো `@Module` এবং `@InstallIn` দিয়ে অ্যানোটেট করা ক্লাস। যদি আমরা কোনো ইন্টারফেসকে একটি কংক্রিট ইমপ্লিমেন্টেশনের সাথে বাইন্ড করতে চাই, তবে সবচেয়ে কার্যকর উপায় হলো `@Binds` ব্যবহার করা । এটি একটি অ্যাবস্ট্রাক্ট ফাংশন সংজ্ঞায়িত করে, যেখানে প্যারামিটারটি হলো ইমপ্লিমেন্টেশন এবং রিটার্ন ভ্যালুটি হলো ইন্টারফেস; এটি মূলত Hilt-কে বলে: "যখন কেউ একটি AnalyticsService চাইবে, তখন তাকে একটি AnalyticsServiceImpl দাও।"

অন্যদিকে, যখন অবজেক্ট তৈরি করার জন্য আরও জটিল লজিকের প্রয়োজন হয় বা এটি কোনো তৃতীয় পক্ষ থেকে আসে, তখন আমরা `@Provides` ব্যবহার করি । এক্ষেত্রে, আমরা একটি সাধারণ ফাংশন লিখি যার বডিতে ইনস্ট্যান্সটি ঠিক কীভাবে তৈরি করা হবে তার বিশদ বিবরণ থাকে, যেমন একটি রেট্রোফিট ক্লায়েন্টের বেস ইউআরএল কনফিগার করার সময়। সংক্ষেপে, যেখানে `@Binds` ডেলিগেশনের জন্য ব্যবহৃত হয়, সেখানে `@Provides` ম্যানুয়ালি ডিপেন্ডেন্সি তৈরি করতে ব্যবহৃত হয় ।

@Qualifier ব্যবহার করে দ্বন্দ্ব ব্যবস্থাপনা

কখনও কখনও আমাদের একই অবজেক্ট টাইপের দুটি ভিন্ন সংস্করণের প্রয়োজন হয়। ধরুন আপনার দুটি OkHttpClient ক্লায়েন্ট আছে: একটি প্রমাণীকরণ-প্রয়োজনীয় কলের জন্য এবং অন্যটি পাবলিক অনুরোধের জন্য। যদি আমরা কোনো অতিরিক্ত ব্যাখ্যা ছাড়াই উভয়কেই ইনজেক্ট করার চেষ্টা করি, তাহলে Hilt প্যানিক করবে, কারণ এটি বুঝতে পারবে না যে কোনটি বেছে নিতে হবে। এই সমস্যা সমাধানের জন্য, আমরা কাস্টম কোয়ালিফায়ার ব্যবহার করি ।

কোয়ালিফায়ার মূলত `@Qualifier` দিয়ে চিহ্নিত একটি কাস্টম অ্যানোটেশন । আমরা `@AuthInterceptorOkHttpClient`-এর মতো ট্যাগ তৈরি করি এবং সেগুলোকে মডিউলের সেই মেথডে রাখি যা ইনস্ট্যান্সটি সরবরাহ করে এবং যেখানে আমরা এটি ইনজেক্ট করি। এইভাবে, Hilt কোনো ত্রুটি ছাড়াই একই ধরনের বাইন্ডিংগুলোর মধ্যে পার্থক্য করতে পারে। এছাড়াও, `@ApplicationContext` এবং `@ActivityContext`-এর মতো খুব দরকারি কিছু প্রি-বিল্ট কোয়ালিফায়ার রয়েছে, যা অ্যান্ড্রয়েড কনটেক্সট পাওয়ার জন্য আমাদের নিজস্ব মডিউল তৈরি করার ঝামেলা থেকে বাঁচায় ।

কোটলিন ফ্লো ব্যবহার করে অ্যাসিঙ্ক্রোনাস এবং রিঅ্যাক্টিভ ডেটা ফ্লো
সম্পর্কিত নিবন্ধ:
অ্যান্ড্রয়েড ডেভেলপমেন্টের জন্য অপরিহার্য কোটলিন ধারণাগুলির সম্পূর্ণ নির্দেশিকা

জীবনচক্র এবং পরিধির সমন্বয়

ডিফল্টরূপে, প্রতিবার কোনো ডিপেন্ডেন্সি অনুরোধ করা হলে Hilt একটি নতুন ইনস্ট্যান্স তৈরি করে। তবে, এমন পরিস্থিতিও রয়েছে যেখানে আমরা চাই যে কম্পোনেন্টের জীবনকাল জুড়ে অবজেক্টটি একই থাকুক। এখানেই স্কোপের ভূমিকা আসে । যদি আমরা কোনো ক্লাসকে `@Singleton` দিয়ে চিহ্নিত করি এবং এটিকে `SingletonComponent`-এ ইনস্টল করি, তাহলে আমাদের কাছে একটিমাত্র ইনস্ট্যান্স থাকবে যা পুরো অ্যাপ্লিকেশন জুড়ে শেয়ার করা হবে।

এছাড়াও আরও সুনির্দিষ্ট স্তর রয়েছে। উদাহরণস্বরূপ, `@ActivityScoped` নিশ্চিত করে যে একটি অ্যাক্টিভিটির জীবনকাল জুড়ে একই ইনস্ট্যান্স ব্যবহৃত হবে, অন্যদিকে `@ViewModelScoped` ViewModel-এর জন্য একই কাজ করে, যা স্ক্রিন ঘোরানোর সময় ডিপেন্ডেন্সিটি পুনরায় তৈরি হওয়া থেকে বিরত রাখে। তবে, স্কোপের অতিরিক্ত ব্যবহার করা বাঞ্ছনীয় নয়, কারণ অবজেক্টগুলোকে খুব বেশি সময় ধরে মেমরিতে রাখলে তা অ্যান্ড্রয়েডের পারফরম্যান্স এবং মেমরি ব্যবস্থাপনার উপর নেতিবাচক প্রভাব ফেলতে পারে।

বিশেষ ক্ষেত্র: @EntryPoint এবং অসমর্থিত ক্লাস

Hilt খুবই শক্তিশালী, কিন্তু এটি সব জায়গায় পৌঁছায় না। কিছু সিস্টেম ক্লাস, যেমন ContentProvider, @AndroidEntryPoint সাপোর্ট করে না। এই ধরনের পরিস্থিতিতে, সমাধান হলো @EntryPoint ব্যবহার করে একটি এন্ট্রি পয়েন্ট তৈরি করা । এটি এমন একটি ইন্টারফেস সংজ্ঞায়িত করে যা Hilt-পরিচালিত কোড এবং বাহ্যিক কোডের মধ্যেকার ব্যবধান পূরণ করে।

এই ব্রিজ থেকে ডিপেন্ডেন্সি পুনরুদ্ধার করতে, আমরা EntryPointAccessors ব্যবহার করি । আমরা এটিকে উপযুক্ত কনটেক্সট এবং EntryPoint ইন্টারফেস পাস করি, যা আমাদেরকে Hilt গ্রাফ থেকে ম্যানুয়ালি ডিপেন্ডেন্সি এক্সট্র্যাক্ট করার সুযোগ দেয়, এমনকি সেইসব এলাকা থেকেও যেখানে অটোমেটিক ইনজেকশন পৌঁছাতে পারে না।

হিল্ট এবং ড্যাগার এর মধ্যে পার্থক্য

হিল্ট ড্যাগার-এর বিকল্প নয়, বরং এর উপর ভিত্তি করে তৈরি। এর প্রধান সুবিধা হলো, এটি ম্যানুয়ালি কম্পোনেন্ট লেখা এবং সেগুলোর লাইফসাইকেল পরিচালনা করার প্রয়োজনীয়তা দূর করে, কারণ এটি স্বয়ংক্রিয়ভাবে অ্যান্ড্রয়েড ক্লাসের সাথে লিঙ্ক করা কন্টেইনার তৈরি করে । এর ফলে পুনরাবৃত্তিমূলক কোড ব্যাপকভাবে কমে যায় এবং প্রজেক্টটি অনেক বেশি পাঠযোগ্য হয়ে ওঠে।

এই সিস্টেমটি নিয়ন্ত্রণের একটি স্বাভাবিক বিপরীতমুখী বিন্যাস তৈরি করে: ক্লাসগুলো তাদের চাহিদা নির্ধারণ করে, এবং হিল্ট সেগুলো সরবরাহ করার দায়িত্ব নেয়। এটি কেবল দৈনন্দিন ডেভেলপমেন্টকেই সহজ করে না, বরং ইউনিট টেস্টিংয়ের জন্যও একটি আশীর্বাদস্বরূপ , কারণ আমরা বিজনেস লজিক পরিবর্তন না করেই বাস্তব ইমপ্লিমেন্টেশনগুলোকে টেস্ট ডাবল দিয়ে প্রতিস্থাপন করতে পারি।

অ্যান্ড্রয়েডে Hilt-এর প্রয়োগ শক্তিশালী ও কার্যকর ডিপেন্ডেন্সি ম্যানেজমেন্ট সক্ষম করে, যা অপ্রয়োজনীয় কোড দূর করে এবং স্কেলেবল অ্যাপ্লিকেশন তৈরিকে সহজতর করে। `@Binds`, `@Provides`, এবং `@Qualifier`- এর সুনির্দিষ্ট ব্যবহারের ফলে ডেভেলপাররা টাইপ কনফ্লিক্ট সমাধান করতে এবং অবজেক্ট লাইফসাইকেলকে সূক্ষ্মভাবে পরিচালনা করতে পারেন, যা ইনভার্সন অফ কন্ট্রোলের মাধ্যমে অ্যাপ্লিকেশনটিকে রক্ষণাবেক্ষণযোগ্য এবং সহজে পরীক্ষাযোগ্য করে তোলে।


Google-এ পছন্দের উৎস হিসেবে যোগ করুন