Jetpack Compose-এ, একটি অবজেক্ট RememberObserver ব্যবহার করে কলব্যাক পেতে পারে যখন এটি remember এর সাথে ব্যবহার করা হয়, তখন কম্পোজিশন হায়ারার্কিতে কখন এটি শুরু হয় এবং কখন মনে রাখা বন্ধ হয় তা জানার জন্য। একইভাবে, আপনি RetainObserver ব্যবহার করে retain ব্যবহার করে কোনও অবজেক্টের অবস্থা সম্পর্কে তথ্য পেতে পারেন।
যেসব অবজেক্ট কম্পোজিশন হায়ারার্কি থেকে এই জীবনচক্রের তথ্য ব্যবহার করে, তাদের জন্য আমরা কয়েকটি সেরা অনুশীলনের সুপারিশ করছি যাতে আপনার অবজেক্টগুলি প্ল্যাটফর্মে ভালো নাগরিক হিসেবে কাজ করে এবং অপব্যবহারের বিরুদ্ধে রক্ষা করে তা যাচাই করা যায়। বিশেষ করে, কনস্ট্রাক্টরের পরিবর্তে কাজ শুরু করতে onRemembered (অথবা onRetained ) কলব্যাক ব্যবহার করুন, অবজেক্টগুলি মনে রাখা বা ধরে রাখা বন্ধ হয়ে গেলে সমস্ত কাজ বাতিল করুন এবং দুর্ঘটনাজনিত কল এড়াতে RememberObserver এবং RetainObserver এর বাস্তবায়ন ফাঁস হওয়া এড়ান। পরবর্তী বিভাগে এই সুপারিশগুলি আরও গভীরভাবে ব্যাখ্যা করা হয়েছে।
RememberObserver এবং RetainObserver দিয়ে আরম্ভ এবং পরিষ্কারকরণ
থিংকিং ইন কম্পোজ গাইড রচনার পিছনের মানসিক মডেল বর্ণনা করে। RememberObserver এবং RetainObserver সাথে কাজ করার সময়, রচনার দুটি আচরণ মনে রাখা গুরুত্বপূর্ণ:
- পুনর্গঠন আশাব্যঞ্জক এবং বাতিল হতে পারে
- সমস্ত কম্পোজেবল ফাংশনের কোনও পার্শ্ব প্রতিক্রিয়া থাকা উচিত নয়
onRemembered বা onRetained এর সময় ইনিশিয়ালাইজেশনের পার্শ্বপ্রতিক্রিয়া চালান, নির্মাণের সময় নয়
যখন বস্তুগুলি মনে রাখা হয় বা ধরে রাখা হয়, তখন গণনা ল্যাম্বডা কম্পোজিশনের অংশ হিসাবে চলে। যে কারণে আপনি কম্পোজিশনের সময় কোনও পার্শ্ব-প্রতিক্রিয়া সম্পাদন করবেন না বা একটি কোরোটিন চালু করবেন না, একই কারণে আপনার remember , retain এবং তাদের বৈচিত্র্যের জন্য পাস করা গণনা ল্যাম্বডাতেও পার্শ্ব-প্রতিক্রিয়া সম্পাদন করা উচিত নয়। এর মধ্যে মনে রাখা বা ধরে রাখা বস্তুগুলির জন্য কনস্ট্রাক্টরের অংশ হিসাবে অন্তর্ভুক্ত।
পরিবর্তে, RememberObserver , অথবা RetainObserver প্রয়োগ করার সময়, যাচাই করুন যে সমস্ত প্রভাব এবং চালু করা কাজগুলি onRemembered কলব্যাকে প্রেরণ করা হয়েছে। এটি SideEffect API-এর মতো একই সময় প্রদান করে। এটি গ্যারান্টি দেয় যে এই প্রভাবগুলি কেবল তখনই কার্যকর হবে যখন রচনাটি প্রয়োগ করা হবে, যা অনাথ কাজ এবং মেমরি লিক প্রতিরোধ করে যদি কোনও পুনর্গঠন পরিত্যক্ত বা বিলম্বিত হয়।
class MyComposeObject : RememberObserver { private val job = Job() private val coroutineScope = CoroutineScope(Dispatchers.Main + job) init { // Not recommended: This will cause work to begin during composition instead of // with other effects. Move this into onRemembered(). coroutineScope.launch { loadData() } } override fun onRemembered() { // Recommended: Move any cancellable or effect-driven work into the onRemembered // callback. If implementing RetainObserver, this should go in onRetained. coroutineScope.launch { loadData() } } private suspend fun loadData() { /* ... */ } // ... }
ভুলে গেলে, অবসর নিলে, অথবা পরিত্যক্ত হলে ভেঙে পড়া
রিসোর্স ফাঁস হওয়া বা ব্যাকগ্রাউন্ড কাজগুলিকে অনাথ না রাখার জন্য, মনে রাখা বস্তুগুলিও নিষ্পত্তি করতে হবে। RememberObserver বাস্তবায়নকারী বস্তুগুলির জন্য, এর অর্থ হল onRemembered এ শুরু করা যেকোনো কিছুর onForgotten এ একটি মিলযুক্ত রিলিজ কল থাকতে হবে।
যেহেতু কম্পোজিশন বাতিল করা যেতে পারে, তাই RememberObserver প্রয়োগকারী বস্তুগুলিকে যদি কম্পোজিশনে পরিত্যক্ত করা হয় তবে সেগুলিও নিজেদের পরিষ্কার করতে হবে। কোনও বস্তু বাতিল হয়ে গেলে বা ব্যর্থ হলে remember দ্বারা ফেরত পাঠানো হলে তা পরিত্যক্ত হয়। (এটি সাধারণত PausableComposition ব্যবহার করার সময় ঘটে এবং Android Studio এর কম্পোজেবল প্রিভিউ টুলিং ব্যবহার করার সময়ও ঘটতে পারে।)
যখন একটি স্মরণযোগ্য বস্তু পরিত্যক্ত হয়, তখন এটি কেবল onAbandoned কলটি গ্রহণ করে (এবং onRemembered কলটি গ্রহণ করে না)। abandon পদ্ধতিটি বাস্তবায়নের জন্য, অবজেক্টটি শুরু হওয়ার সময় এবং অবজেক্টটি onRemembered কলব্যাক পাওয়ার সময়কালের মধ্যে তৈরি হওয়া যেকোনো কিছু নিষ্পত্তি করুন।
class MyComposeObject : RememberObserver { private val job = Job() private val coroutineScope = CoroutineScope(Dispatchers.Main + job) // ... override fun onForgotten() { // Cancel work launched from onRemembered. If implementing RetainObserver, onRetired // should cancel work launched from onRetained. job.cancel() } override fun onAbandoned() { // If any work was launched by the constructor as part of remembering the object, // you must cancel that work in this callback. For work done as part of the construction // during retain, this code should will appear in onUnused. job.cancel() } }
RememberObserver এবং RetainObserver বাস্তবায়নগুলিকে ব্যক্তিগত রাখুন
পাবলিক API লেখার সময়, RememberObserver এবং RetainObserver এক্সটেনশন করার সময় সাবধানতা অবলম্বন করুন, যখন এমন ক্লাস তৈরি করা হয় যা পাবলিকলি রিটার্ন করা হয়। একজন ব্যবহারকারী আপনার অবজেক্টটি যখন আপনি আশা করেন তখন মনে রাখতে পারেন না, অথবা আপনার অবজেক্টটি আপনার ইচ্ছার চেয়ে ভিন্নভাবে মনে রাখতে পারেন। এই কারণে, আমরা RememberObserver বা RetainObserver বাস্তবায়নকারী অবজেক্টের জন্য কনস্ট্রাক্টর বা ফ্যাক্টরি ফাংশন প্রকাশ না করার পরামর্শ দিই। মনে রাখবেন যে এটি একটি ক্লাসের রানটাইম ধরণের উপর নির্ভর করে, ঘোষিত ধরণের উপর নয় — এমন একটি অবজেক্ট মনে রাখার ফলে যা RememberObserver বা RetainObserver বাস্তবায়ন করে কিন্তু Any তে কাস্ট করা হয় তবুও অবজেক্টটি কলব্যাক গ্রহণ করে।
সুপারিশ করা হয় না:
abstract class MyManager
// Not Recommended: Exposing a public constructor (even implicitly) for an object implementing
// RememberObserver can cause unexpected invocations if it is remembered multiple times.
class MyComposeManager : MyManager(), RememberObserver { ... }
// Not Recommended: The return type may be an implementation of RememberObserver and should be
// remembered explicitly.
fun createFoo(): MyManager = MyComposeManager()
প্রস্তাবিত:
abstract class MyManager class MyComposeManager : MyManager() { // Callers that construct this object must manually call initialize and teardown fun initialize() { /*...*/ } fun teardown() { /*...*/ } } @Composable fun rememberMyManager(): MyManager { // Protect the RememberObserver implementation by never exposing it outside the library return remember { object : RememberObserver { val manager = MyComposeManager() override fun onRemembered() = manager.initialize() override fun onForgotten() = manager.teardown() override fun onAbandoned() { /* Nothing to do if manager hasn't initialized */ } } }.manager }
বস্তু মনে রাখার সময় বিবেচনার বিষয়গুলি
RememberObserver এবং RetainObserver সম্পর্কিত পূর্ববর্তী সুপারিশগুলির পাশাপাশি, আমরা কর্মক্ষমতা এবং সঠিকতা উভয়ের জন্যই দুর্ঘটনাক্রমে পুনরায় মনে রাখা বস্তুগুলি সম্পর্কে সচেতন থাকার এবং এড়িয়ে চলার পরামর্শ দিই। নিম্নলিখিত বিভাগগুলিতে নির্দিষ্ট পুনরায় মনে রাখার পরিস্থিতি এবং কেন সেগুলি এড়ানো উচিত সে সম্পর্কে আরও গভীরভাবে আলোচনা করা হয়েছে।
শুধুমাত্র একবার জিনিস মনে রাখবেন
কোনও বস্তু পুনরায় মনে রাখা বিপজ্জনক হতে পারে। সবচেয়ে ভালো ক্ষেত্রে, আপনি ইতিমধ্যেই মনে রাখা মান মনে রাখার জন্য সম্পদ নষ্ট করতে পারেন। কিন্তু যদি কোনও বস্তু RememberObserver প্রয়োগ করে এবং অপ্রত্যাশিতভাবে দুবার মনে রাখা হয়, তাহলে এটি প্রত্যাশার চেয়ে বেশি কলব্যাক পাবে। এটি সমস্যার সৃষ্টি করতে পারে, কারণ onRemembered এবং onForgotten লজিক দুবার কার্যকর হবে, এবং RememberObserver এর বেশিরভাগ বাস্তবায়ন এই ক্ষেত্রে সমর্থন করে না। যদি দ্বিতীয়বার মনে রাখার কলটি একটি ভিন্ন স্কোপে ঘটে যার আয়ু মূল remember থেকে আলাদা, তাহলে RememberObserver.onForgotten এর অনেক বাস্তবায়ন বস্তুটি ব্যবহার শেষ হওয়ার আগেই তা নিষ্পত্তি করে।
val first: RememberObserver = rememberFoo()
// Not Recommended: Re-remembered `Foo` now gets double callbacks
val second = remember { first }
এই পরামর্শটি সেইসব বস্তুর ক্ষেত্রে প্রযোজ্য নয় যেগুলো আবার ট্রানজিটলি মনে রাখা হয় (যেমন, মনে রাখা বস্তু যা অন্য মনে রাখা বস্তুকে গ্রাস করে)। নিম্নরূপ দেখতে কোড লেখা সাধারণ, যা অনুমোদিত কারণ একটি ভিন্ন বস্তু মনে রাখা হচ্ছে এবং তাই অপ্রত্যাশিত কলব্যাক দ্বিগুণ হওয়ার কারণ হয় না।
val foo: Foo = rememberFoo() // Acceptable: val bar: Bar = remember { Bar(foo) } // Recommended key usage: val barWithKey: Bar = remember(foo) { Bar(foo) }
ধরে নিন ফাংশন আর্গুমেন্টগুলি ইতিমধ্যেই মনে রাখা হয়েছে
একটি ফাংশনের তার কোনও প্যারামিটার মনে রাখা উচিত নয় কারণ এটি RememberObserver জন্য দ্বিগুণ কলব্যাক ইনভোকেশনের দিকে পরিচালিত করতে পারে এবং এটি অপ্রয়োজনীয়। যদি একটি ইনপুট প্যারামিটার মনে রাখতে হয়, তাহলে হয় যাচাই করুন যে এটি RememberObserver বাস্তবায়ন করছে না, অথবা কলারদের তাদের যুক্তি মনে রাখতে হবে।
@Composable
fun MyComposable(
parameter: Foo
) {
// Not Recommended: Input should be remembered by the caller.
val rememberedParameter = remember { parameter }
}
এটি ট্রানজিটলি মনে রাখা বস্তুর ক্ষেত্রে প্রযোজ্য নয়। ফাংশনের আর্গুমেন্ট থেকে প্রাপ্ত বস্তু মনে রাখার সময়, এটি remember জন্য একটি কী হিসাবে উল্লেখ করার কথা বিবেচনা করুন:
@Composable fun MyComposable( parameter: Foo ) { // Acceptable: val derivedValue = remember { Bar(parameter) } // Also Acceptable: val derivedValueWithKey = remember(parameter) { Bar(parameter) } }
এমন কোনও জিনিস ধরে রাখবেন না যা ইতিমধ্যে মনে আছে
কোনও বস্তু পুনরায় মনে রাখার মতোই, আপনার মনে রাখা বস্তুর আয়ুষ্কাল বাড়ানোর চেষ্টা করার জন্য তা ধরে রাখা এড়িয়ে চলা উচিত। এটি স্টেট লাইফস্প্যানের পরামর্শের একটি ফল: retain ব্যবহার করা উচিত নয় এমন বস্তুর সাথে যার আয়ুষ্কাল রিটেন অফারের সাথে মেলে না। যেহেতু remembered বস্তুর আয়ুষ্কাল retained অফারের সাথে মেলে না, তাই আপনার মনে রাখা বস্তুটি ধরে রাখা উচিত নয়। পরিবর্তে, বস্তুটিকে মনে রাখার পরিবর্তে মূল স্থানে ধরে রাখা পছন্দ করুন।