যদি আপনার কখনো বিখ্যাত কারো সাথে ঝগড়া হয়ে থাকে কলব্যাক হেল আপনার অ্যাপ যদি কখনো অপ্রত্যাশিতভাবে ক্র্যাশ করে থাকে, তাহলে আপনি জানেন যে অ্যান্ড্রয়েডে অ্যাসিঙ্ক্রোনিসিটি পরিচালনা করা কতটা ঝামেলার হতে পারে। কোটলিন কোরাউটিন এই সমস্যার সমাধান নিয়ে এসেছে, যা আমাদের এমন কোড লেখার সুযোগ করে দেয় যা দেখতে সরল ও সরল মনে হলেও নেপথ্যে চমৎকারভাবে কাজ করে। এটি স্ক্রিনে ব্যবহারকারীর কোনো রকম ল্যাগ বা ধীরগতি টের পাওয়ার আগেই থ্রেডগুলোর মধ্যে কাজ স্থানান্তর করে দেয়।
সমস্যাটি তখনই দেখা দেয় যখন আমরা এমন টাস্ক চালু করি যা স্ক্রিন বন্ধ হওয়ার পরেও "আটকে" থাকে, যা সরাসরি সেই ভয়ংকর মেমোরি লিকের কারণ হয়। অ্যাপটি যাতে ডিভাইসের র্যাম ব্যবহার না করে, তা প্রতিরোধ করার জন্য এই টাস্কগুলো কোথায় এবং কীভাবে চালু করতে হবে, তা আমাদের পুরোপুরি বুঝতে হবে। এখানেই মূল বিষয়টি আসে। জীবনচক্রের জন্য অপ্টিমাইজ করা পরিধিযেগুলো কোনো যন্ত্রাংশ বিকল হয়ে গেলে স্বয়ংক্রিয়ভাবে সৃষ্ট ময়লা পরিষ্কার করার জন্য দায়ী।
কো-রুটিন স্কোপ বোঝা: এখানে দায়িত্বে কে আছেন?
স্কোপ হলো একটি সীমানা যা নির্ধারণ করে একটি কো-রুটিন কতক্ষণ চালু থাকবে। যদি আমরা এমন কোনো স্কোপে কিছু চালাই যা আর বৈধ নয়, তাহলে কো-রুটিনটি শূন্যে চলতে থাকে, রিসোর্স ব্যবহার করে এবং এমন সব অবজেক্টের রেফারেন্স ধরে রাখে যা ইতোমধ্যেই মুছে ফেলা উচিত ছিল। এটি প্রতিরোধ করার জন্য, অ্যান্ড্রয়েড কয়েকটি পূর্ব-কনফিগার করা টুল সরবরাহ করে।
El ভিউমডেলস্কোপ এটি বিজনেস লজিকের জন্য সেরা বিকল্প। এটি সরাসরি ViewModel-এর লাইফসাইকেলের সাথে যুক্ত; অর্থাৎ, যে মুহূর্তে ViewModel-টি ডেস্ট্রয় হয়ে যায় (কারণ ব্যবহারকারী স্থায়ীভাবে স্ক্রিনটি ছেড়ে চলে গেছেন), সেখানে শুরু হওয়া সমস্ত টাস্ক একবারে বাতিল হয়ে যায়। এমন ডেটা প্রসেস করার জন্য এটি একটি আদর্শ বিকল্প, যা ভিউ ডেস্ট্রয়ের পরেও টিকে থাকা উচিত নয়, কিন্তু স্ক্রিন রোটেশনের মতো কনফিগারেশন পরিবর্তনেও অক্ষত থাকা প্রয়োজন।
অন্যদিকে, আমাদের আছে জীবনচক্রের পরিধিযা LifecycleOwner-এর সাথে সংযুক্ত থাকে, সেটা Activity হোক বা Fragment। Activity-টি ধ্বংস হওয়ার সাথে সাথে যদি আপনার কোনো কাজ বন্ধ করার প্রয়োজন হয়, তবে এটিই আপনার জন্য সঠিক জায়গা। এছাড়াও, এই জগতে জেটপ্যাক রচনাআমাদের আছে LaunchedEffectসঠিকের জন্য কম্পোজ-এর সাইড এফেক্টস কন্ট্রোল এলিমেন্টের কম্পোজিশনের সাথে লিঙ্কযুক্ত একটি স্কোপ তৈরি করে। যদি কম্পোনেন্টটি স্ক্রিনের বাইরে চলে যায়, তাহলে কো-রুটিনটি বাতিল হয়ে যায়, ফলে ব্যাকগ্রাউন্ডে অপ্রয়োজনীয়ভাবে অ্যানিমেশন বা নেটওয়ার্ক কল চলতে পারে না।
ডিসপ্যাচার: ইন্টারফেস ব্লক না করার কৌশল
কো-রুটিন চালু করাটা কাজের অর্ধেক মাত্র; এখন আপনাকে ঠিক করতে হবে এটি কোন থ্রেডে চলবে। আপনি যদি মেইন থ্রেডে ডাটাবেস রিকোয়েস্ট করার চেষ্টা করেন, তাহলে অ্যান্ড্রয়েড একটি এরর দেখাবে অথবা, আরও খারাপভাবে, ইন্টারফেসটি ফ্রিজ হয়ে যাবে এবং ব্যবহারকারী মনে করবে অ্যাপটি ক্র্যাশ করেছে।
- প্রেরণকারীগণ। প্রধান: এটি UI থ্রেড। আপনার শুধু খুব দ্রুত কাজ করার জন্য এটি ব্যবহার করা উচিত, যেমন টেক্সট আপডেট করা বা একটি বাটন দেখানো। যেকোনো ভারী কাজ এখানে এটা একটা গুরুতর পাপ।
- ডিসপ্যাচারস.আইও: এটি ফাইল পড়া, রুমে লেখা বা HTTP অনুরোধ করার মতো ইনপুট/আউটপুট অপারেশনের জন্য অপ্টিমাইজ করা হয়েছে। এটি একটি ইলাস্টিক থ্রেড পুল ব্যবহার করে যা অনুমতি দেয় একই সাথে অনেক কাজ যেহেতু সিপিইউ সাধারণত নেটওয়ার্ক থেকে প্রতিক্রিয়ার জন্য অপেক্ষা করতে খুব বেশি ব্যস্ত থাকে না।
- ডিসপ্যাচার। ডিফল্টএটি নিবিড় গণনার মূল চালিকাশক্তি। যদি আপনাকে একটি বিশাল JSON ফাইল পার্স করতে বা হাজার হাজার উপাদানের একটি তালিকা ফিল্টার করতে হয়, তবে এই ডিসপ্যাচারটি এর উপর ভিত্তি করে বেশ কয়েকটি থ্রেড ব্যবহার করে... আপনার সিপিইউ-এর আসল কোরগুলি সমান্তরালতার পূর্ণ সদ্ব্যবহার করতে।
এখানে সবচেয়ে বড় কৌশলটি হলো ব্যবহার করা withContextএটি আপনাকে একটি স্থগিত ফাংশনের মাঝখানে থ্রেড পরিবর্তন করার সুযোগ দেয়। আপনি Main থেকে শুরু করে, একটি ফাইল ডাউনলোড করার জন্য IO-তে যেতে পারেন, এবং স্বয়ংক্রিয়ভাবে প্রধান থ্রেডে ফিরে যান একটিও কলব্যাক না লিখে ফলাফলটি দেখানো।
কনকারেন্সি এবং প্যারালেলিজম: লঞ্চ বনাম অ্যাসিঙ্ক
সব অ্যাসিঙ্ক্রোনাস টাস্ক একরকম হয় না। কখনও কখনও আমরা শুধু চাই কিছু একটা ঘটে যাক (কাজটা করে ভুলে যেতে), আবার কখনও সামনে এগিয়ে যাওয়ার জন্য আমাদের একটি ফলাফলের প্রয়োজন হয়। এর জন্য আমাদের দুটি মৌলিক ভিত্তি রয়েছে।
কমান্ড launch এটি সবচেয়ে সাধারণ। এটি টাস্কটি চালু করে এবং একটি রিটার্ন করে। কাজের বস্তুযা কো-রুটিন পরিচালনার জন্য একটি রিমোট কন্ট্রোলের মতো। এই জবটির মাধ্যমে, ব্যবহারকারী যদি ম্যানুয়ালি অপারেশনটি বাতিল করার সিদ্ধান্ত নেন, তবে আমরা টাস্কটি বাতিল করতে পারি।
যদি আমাদের একটি রিটার্ন ভ্যালুর প্রয়োজন হয়, আমরা ব্যবহার করি asyncএই কনস্ট্রাক্টরটি একটি রিটার্ন করে Deferredযা মূলত একটি প্রতিশ্রুতি যে একটি ফলাফল পাওয়া যাবে। মজার ব্যাপার হলো, আমরা async ব্যবহার করে একাধিক টাস্ক চালু করতে পারি এবং তারপর কল করতে পারি। await() জন্য ফলাফলগুলি একত্রিত করুনআপনার ফোনে যদি কোয়াড-কোর প্রসেসর থাকে এবং আপনি Dispatchers.Default-এ টাস্ক চালু করেন, তাহলে দেখবেন যে সেগুলো সত্যিকারের সমান্তরালে চলে, যা অপেক্ষার সময় ব্যাপকভাবে কমিয়ে দেয়।
Flow এবং StateFlow সহ প্রতিক্রিয়াশীল ডেটা প্রবাহ
যখন আমাদের একটিমাত্র মানের প্রয়োজন হয় না, বরং সময়ের সাথে সাথে পরিবর্তিত হওয়া তথ্যের একটি প্রবাহের প্রয়োজন হয়, তখন আমরা ব্যবহার করি ফ্লোসাধারণ কো-রুটিনের মতো নয়, একটি ফ্লো হলো "কোল্ড", অর্থাৎ কেউ এতে সাবস্ক্রাইব না করা পর্যন্ত এটি কাজ করা শুরু করে না। collect.
আধুনিক উন্নয়নে, আদর্শ হলো সেই প্রবাহগুলোকে রূপান্তর করা স্টেটফ্লো অপারেটর ব্যবহার করে stateIn একটি ViewModel-এর ভিতরে, একটি অনুসরণ করে StateFlow এবং SharedFlow-এর সম্পূর্ণ নির্দেশিকাএর ফলে, ডিভাইস ঘোরানো হলেও UI সর্বদা সর্বশেষ নির্গত অবস্থাটি অ্যাক্সেস করতে পারে। Compose-এ এই ডেটা নিরাপদে ব্যবহার করার জন্য, সুপারিশ করা হয় যে এটি ব্যবহার করুন collectAsStateWithLifecycleএই ফাংশনটি গুরুত্বপূর্ণ কারণ সংগ্রহ বন্ধ করে দেয় অ্যাপটি ব্যাকগ্রাউন্ডে গেলে বুদ্ধিমত্তার সাথে ব্যাটারি ও মেমরি সাশ্রয় করে।
শক্তিশালী কোডের জন্য উন্নত কৌশল
আমাদের অ্যাপটিকে তাসের ঘরের মতো ভেঙে পড়া থেকে বাঁচাতে, আমাদের অবশ্যই ত্রুটি সামলাতে হবে। কো-রুটিনে, এক্সেপশনগুলো উপরের দিকে ছড়িয়ে পড়ে। যদি কোনো চাইল্ড ফেইল করে, তাহলে প্যারেন্টও ফেইল করে, যদি না আমরা একটি বিশেষ পদ্ধতি ব্যবহার করি। সুপারভাইজারের চাকরিস্বতন্ত্র কাজ চালু করার ক্ষেত্রে এটি অত্যন্ত গুরুত্বপূর্ণ, কারণ একটি ডাউনলোড ব্যর্থ হলে যেন অন্যগুলোর ডাউনলোড বাতিল না হয়ে যায়।
এছাড়াও, এটা মনে রাখা জরুরি যে ক্যান্সেলেশন একটি কোঅপারেটিভ প্রক্রিয়া। যদি আপনার একটি লুপ লক্ষ লক্ষ ডেটা পয়েন্ট প্রসেস করে, তবে শুধু স্কোপটি ক্যানসেল করলেই কো-রুটিনটি নিজে থেকে বন্ধ হয়ে যাবে না; আপনাকে অবশ্যই `cancel` কল করতে হবে। ensureActive() অথবা পরীক্ষা করুন isActive যাতে রুটিনটি জেনে রাখো তোমাকে মরতেই হবে এবং সম্পদগুলো মুক্ত করুন।
অ্যান্ড্রয়েড স্কোপের সঠিক ব্যবহার, উপযুক্ত ডিসপ্যাচার নির্বাচন এবং রিঅ্যাক্টিভ ফ্লো-এর বাস্তবায়ন যেকোনো পেশাদার অ্যাপ্লিকেশনের ভিত্তি তৈরি করে। লাইফসাইকেল ম্যানেজমেন্টের দায়িত্ব অর্পণের মাধ্যমে... viewModelScope y lifecycleScopeভারী কাজগুলো I/O বা ডিফল্ট থ্রেডে স্থানান্তর করার মাধ্যমে আমরা ক্র্যাশ ছাড়াই একটি মসৃণ ব্যবহারকারীর অভিজ্ঞতা অর্জন করি এবং সর্বোপরি, এটি মেমরি লিক থেকে মুক্ত থাকে যা ডিভাইসের কর্মক্ষমতাকে ক্ষতিগ্রস্ত করে।