আপনি যদি কোটলিনের মাধ্যমে রিঅ্যাক্টিভ প্রোগ্রামিংয়ের জগতে প্রবেশ করে থাকেন, তাহলে সম্ভবত এতক্ষণে বুঝতে পেরেছেন যে ডেটা প্রবাহ পরিচালনা করা মোটেই সহজ কাজ নয়। কোটলিন ফ্লোস RxJava-এর মতো আরও জটিল লাইব্রেরিগুলোকে প্রতিস্থাপন করতে এরা এসেছে, যা কো-রুটিনের শক্তির পূর্ণ সদ্ব্যবহার করে অ্যাসিঙ্ক্রোনাস সিকোয়েন্স পরিচালনার জন্য অনেক বেশি স্বাভাবিক ও সরল একটি উপায় প্রদান করে।
এমন একটি ওয়ার্কফ্লো থেকে, যা কেবল অনুরোধ করলেই সক্রিয় হয়, এমন একটি ওয়ার্কফ্লোতে কীভাবে পরিবর্তন আনা যায় যা সর্বদা উপলব্ধ এবং তথ্য প্রদানের জন্য প্রস্তুত থাকে, তা বোঝা আপনার অ্যাপ্লিকেশনকে যথেচ্ছভাবে রিসোর্স ব্যবহার করা থেকে বিরত রাখার জন্য অত্যন্ত গুরুত্বপূর্ণ। এখানেই ধারণাগুলো আসে ঠান্ডা এবং গরম প্রবাহএবং একটি মসৃণ ও নির্বিঘ্ন ব্যবহারকারীর অভিজ্ঞতা নিশ্চিত করতে নির্দিষ্ট সরঞ্জাম ব্যবহার করে কীভাবে সেগুলোকে রূপান্তর করা যায়।
কোল্ড ফ্লোস-এর সারমর্ম
ডিফল্টরূপে, কোটলিনে ফ্লোগুলো কোল্ড হয়। এর মানে হলো, এগুলো মূলত রান্নার রেসিপির মতো: যতক্ষণ না কেউ কোডটি চালানোর সিদ্ধান্ত নেয়, ততক্ষণ এটি রান করে না। collect() ফাংশনটি কল করুনযদি দুটি কালেক্টর একই কোল্ড স্ট্রিম শোনে, তাহলে প্রডিউসারটি শুরু থেকে দুইবার চলবে, যা এপিআই রিকোয়েস্ট বা ভারী ডাটাবেস কোয়েরি করার ক্ষেত্রে একটি মারাত্মক সমস্যা হতে পারে।
এই প্রবাহগুলো স্থাপন করার বিভিন্ন উপায় আছে। পদ্ধতিটি হলো asFlow() বিদ্যমান সংগ্রহগুলো রূপান্তর করার জন্য এটি আদর্শ; flowOf() এটি পূর্বনির্ধারিত মান এবং কনস্ট্রাক্টরের জন্য ব্যবহৃত হয়। প্রবাহ { … } এটি সবচেয়ে নমনীয়, কারণ এটি আপনাকে emit() ফাংশন ব্যবহার করে মান নির্গত করতে এবং কোনো জটিলতা ছাড়াই সাসপেনশন ফাংশন কার্যকর করতে দেয়।
এর প্রক্রিয়াকরণের ক্ষেত্রে, প্রবাহগুলো অনুক্রমিক, যার অর্থ হলো তারা একটি পর্ব শেষ হওয়ার জন্য অপেক্ষা করে। পরবর্তীটিতে যাওয়ার আগে। এই ডেটা পরিচালনা করার জন্য, আমাদের কাছে map() বা filter() এর মতো মধ্যবর্তী অপারেটর রয়েছে, যা পূর্ববর্তীটিকে রূপান্তরিত করে একটি নতুন প্রবাহ তৈরি করে, এবং collect() বা first() এর মতো টার্মিনাল অপারেটর রয়েছে, যেগুলো আসলে ডেটা স্থানান্তর করে। প্রবাহটির কার্যকারিতা শুরু করুন.
হট ফ্লো-এর জগতে প্রবেশ
কোল্ড ফ্লো-এর মতো নয়, হট ফ্লো কাজ শুরু করার জন্য কোনো গ্রাহকের অপেক্ষা করে না; এগুলো সক্রিয় থাকে এবং স্মৃতিতে রয়ে যাওয়া কে শুনছে তা নির্বিশেষে। যেসব পরিস্থিতিতে আপনাকে একটি সাধারণ স্ট্যাটাস শেয়ার করতে হবে বা এমন কোনো ইভেন্ট সম্প্রচার করতে হবে যা একই সময়ে অ্যাপের একাধিক অংশে পৌঁছায়, সেগুলোর জন্য এগুলো আদর্শ।
এই বাস্তুতন্ত্রের মধ্যে দুটি প্রধান পক্ষ রয়েছে: স্টেটফ্লো এবং শেয়ার্ডফ্লোপ্রথমটি একটি স্টেট কন্টেইনারের মতো, যা সর্বদা সর্বশেষ প্রদত্ত মান মনে রাখে এবং যেকোনো নতুন সাবস্ক্রাইবারের কাছে তা সঙ্গে সঙ্গে পৌঁছে দেয়। এটি LiveData-এর আধুনিক বিকল্প, যদিও এর জন্য বাধ্যতামূলক সেটআপ প্রয়োজন। আপনার কনস্ট্রাক্টরে প্রাথমিক মান.
অন্যদিকে, SharedFlow অনেকটা ইভেন্ট বাসের মতো। এটির কোনো প্রাথমিক মানের প্রয়োজন হয় না এবং এটি একটি আদর্শ টুল। অনন্য ইভেন্টগুলি পরিচালনা করুনযেমন নেভিগেশন বা একটি ত্রুটি বার্তা, কারণ এটি ডিফল্ট অবস্থা (যদি রিপ্লে ০ হয়) ধরে রাখে না, ফলে স্ক্রিন ঘোরানোর সময় ইভেন্টটি পুনরায় ট্রিগার হতে পারে না।
stateIn এবং shareIn এর সাথে রূপান্তর
অ্যান্ড্রয়েড আর্কিটেকচার অপ্টিমাইজ করার জন্য কোল্ড ফ্লোকে হট ফ্লোতে রূপান্তর করা অপরিহার্য। কোল্ড ফ্লো থেকে স্টেটফ্লো তৈরি করতে আমরা অপারেটরটি ব্যবহার করি। রাজ্যএই অপারেটরটির সঠিকভাবে কাজ করার জন্য একটি CoroutineScope (সাধারণত viewModelScope), একটি স্টার্টআপ পলিসি এবং একটি প্রাথমিক মান প্রয়োজন।
বর্তমান অবস্থা বজায় না রেখে যদি ইভেন্টের প্রচার করা হয়, তাহলে বিকল্পটি হলো শেয়ারইনএখানে আমরা নতুন গ্রাহকদের জন্য কতগুলো আইটেম পুনরাবৃত্তি হবে এবং আচরণ নীতি নির্ধারণ করি। সবচেয়ে সাধারণ বিকল্পগুলোর মধ্যে একটি হলো শেয়ারিং শুরু হয়েছে। সাবস্ক্রাইব থাকা অবস্থায় (5000)যা শেষ গ্রাহকের পর ৫ সেকেন্ডের জন্য প্রবাহটিকে সক্রিয় রাখে, ফলে স্ক্রিন ঘোরানোর কারণে ডেটা লোডিং পুনরায় শুরু হয় না।
এই পার্থক্যটি বোঝা অত্যাবশ্যক যে, stateIn প্রপার্টির মাধ্যমে সিনক্রোনাস অ্যাক্সেস সহ একটি StateFlow তৈরি করে। মানshareIn এমন একটি SharedFlow তৈরি করে যা বাফার কনফিগারেশন এবং ব্যাকপ্রেশার ব্যবস্থাপনার ক্ষেত্রে আরও নমনীয়, যা বিভিন্ন পলিসির মাধ্যমে সম্পন্ন হয়, যেমন— বাফারওভারফ্লো.ড্রপ_ওল্ডেস্ট.
নিরাপদ সংগ্রহ এবং জীবনচক্র
শুধু একটি হট স্ট্রিম থাকাই যথেষ্ট নয়; এটি কীভাবে ব্যবহার করতে হয় তাও জানতে হবে। যদি আপনি UI-তে একটি সাধারণ `launch`-এর মধ্যে `collect()` ব্যবহার করেন, তাহলে এই ঝুঁকি থেকে যায় যে... পটভূমিতে ডেটা প্রক্রিয়াকরণ চালিয়ে যানএর ফলে মেমরি লিক বা ক্র্যাশ হতে পারে। এর আদর্শ সমাধান হলো ব্যবহার করা repeatOnLifecycle(Lifecycle.State.STARTED).
এই API নিশ্চিত করে যে ভিউটি STOPPED অবস্থায় প্রবেশ করলে ডেটা সংগ্রহ বন্ধ হয়ে যায় এবং STARTED অবস্থায় ফিরে এলে তা পুনরায় শুরু হয়। Jetpack Compose-এর ক্ষেত্রে, এর বিকল্পটি হলো স্টেট ম্যানেজমেন্টের জন্য collectAsStateWithLifecycle()যা হুবহু একই কাজ করে: অ্যাপটি দৃশ্যমান না থাকলে এটি শোনা বন্ধ করে দেয়, যার ফলে বুদ্ধিমত্তার সাথে ব্যাটারি এবং সিপিইউ সাশ্রয় হয়।
প্রবাহের জন্য পরীক্ষার কৌশল
হট ফ্লো পরীক্ষা করা বেশ জটিল। শুধুমাত্র চূড়ান্ত মান দেখাই যথেষ্ট নয়, কারণ স্টেটফ্লো কনফ্লেশনের কারণে আপনি মধ্যবর্তী অবস্থাগুলো এড়িয়ে যেতে পারেন। এর সমাধান করতে, লাইব্রেরিটি ঘূর্ণযন্ত্র এটি একটি প্রধান টুলে পরিণত হয়েছে, যা আপনাকে awaitItem() ব্যবহার করে একটি সুনির্দিষ্ট উপায়ে নির্দিষ্ট নির্গমনের জন্য অপেক্ষা করার সুযোগ দেয়।
stateIn ব্যবহার করে এমন কোনো ViewModel পরীক্ষা করার সময়, এটি ভুলে যাওয়া একটি সাধারণ ভুল যে অন্তত একটি সক্রিয় সংগ্রাহক থাকতে হবে। টেস্ট চলাকালীন, যদি কেউ না শোনে, তাহলে stateIn অপারেটরটি অন্তর্নিহিত ফ্লো সক্রিয় করবে না এবং value প্রপার্টিতে মানগুলো কখনোই আপডেট হবে না, যার ফলে কোনো আপাত কারণ ছাড়াই টেস্টটি ব্যর্থ হবে।
শীতল প্রবাহের জন্য, ব্যবহার নকল সংগ্রহস্থল যা পূর্বনির্ধারিত মান নির্গত করে। আমরা first() দিয়ে প্রথম নির্গমনটি যাচাই করতে পারি অথবা toList() দিয়ে স্ট্রিমটিকে একটি লিস্টে রূপান্তর করতে পারি, যতক্ষণ পর্যন্ত সিকোয়েন্সটি সসীম থাকে, এবং এর মাধ্যমে কোডটি প্রোডাকশনে ডেপ্লয় করার আগে বিজনেস লজিকটি প্রত্যাশিতভাবে কাজ করছে কিনা তা নিশ্চিত করতে পারি।
`stateIn` এবং `shareIn` ব্যবহার করে কোল্ড থেকে হট ডেটা ফ্লোতে রূপান্তর আয়ত্ত করার মাধ্যমে আপনি আরও অনেক বেশি শক্তিশালী অ্যান্ড্রয়েড অ্যাপ্লিকেশন তৈরি করতে পারেন, যেখানে ইন্টারফেস স্টেট ম্যানেজমেন্ট এবং ইভেন্ট এমিশন স্পষ্টভাবে পৃথক থাকে। যদিও কোল্ড ফ্লো অন-ডিমান্ড ডেটা পাইপলাইনের জন্য আদর্শ, হট ফ্লো নিশ্চিত করে যে তথ্য সহজলভ্য এবং দক্ষতার সাথে শেয়ার করা হচ্ছে, তবে শর্ত হলো `repeatOnLifecycle` ব্যবহার করে লাইফসাইকেলগুলো মেনে চলতে হবে এবং Turbine-এর মতো টুল দিয়ে তা যথাযথভাবে যাচাই করতে হবে।