Compose, ধরনকে স্থিতিশীল বা অস্থিতিশীল হিসেবে বিবেচনা করে। কোনও টাইপ স্থিতিশীল হয় যদি সেটি পরিবর্তনযোগ্য না হয় অথবা যদি কম্পোজের পক্ষে এটি জানা সম্ভব হয় যে রিকম্পোজিশনের মধ্যে সেটির ভ্যালু পরিবর্তিত হয়েছে কিনা। কোনও টাইপ অস্থির হয় যদি কম্পোজ পুনঃকম্পোজ করার মধ্যে সেটির ভ্যালু পরিবর্তিত হয়েছে কিনা তা বুঝতে না পারে।
Compose, ইনপুট কীভাবে তুলনা করতে হবে এবং রিকম্পোজিশনের (Kotlin 2.0.20-এ ডিফল্ট হিসেবে চালু থাকা স্ট্রং স্কিপিং মোড) সময় কম্পোজেবলটি এড়িয়ে যাওয়া যাবে কিনা তা নির্ধারণ করতে কম্পোজেবলের প্যারামিটারের স্টেবিলিটি ব্যবহার করে:
- স্টেবল প্যারামিটার: কম্পোজ স্ট্রাকচারাল
ইকুয়ালিটি (
Object.equals()) ব্যবহার করে স্টেবল প্যারামিটার তুলনা করে। কোনও কম্পোজ করার উপযুক্ত আইটেমের স্টেবল প্যারামিটার যদি তার আগের ভ্যালুর সমান হয়, তাহলে কম্পোজ সেটি এড়িয়ে যায়। - অস্থির প্যারামিটার: স্ট্রং স্কিপিং মোড চালু থাকলে (Kotlin 2.0.20 ও এর পরের যেকোনও ভার্সনে
ডিফল্ট), Compose ইনস্ট্যান্স ইকুয়ালিটি (
===) ব্যবহার করে অস্থির প্যারামিটার তুলনা করে এবং একই অবজেক্ট ইনস্ট্যান্স পাস করা হলে কম্পোজ করার উপযুক্ত আইটেম স্কিপ করে। Kotlin 2.0.20-এর আগের ভার্সনে (অথবা Strong skipping মোড বন্ধ করা থাকলে), প্যারেন্ট কম্পোজ করার সময় Compose সবসময় অস্থিতিশীল প্যারামিটার সহ কম্পোজ করার মতো আইটেম আবার কম্পোজ করে।
আপনার অ্যাপ যদি ঘন ঘন অস্থির প্যারামিটারের নতুন ইনস্ট্যান্স অ্যাসাইন করে—অথবা মডেলকে অতিরিক্ত অ্যানোটেশন করে
বড় সংগ্রহে ব্যয়বহুল .equals() চেক করতে বাধ্য করে—তাহলে আপনি
অপ্রয়োজনীয় রিকম্পোজিশন বা তুলনা সংক্রান্ত ওভারহেড দেখতে পেতে পারেন।
এই ডকুমেন্ট থেকে Compose কীভাবে স্থিতিশীলতা নির্ধারণ করে এবং পারফর্ম্যান্স ও সামগ্রিক ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে কীভাবে এটি অপ্টিমাইজ করতে পারবেন সেই বিষয়ে বিস্তারিত জানতে পারবেন।
পরিবর্তনযোগ্য নয় এমন অবজেক্ট
নিচের স্নিপেট থেকে স্থিতিশীলতা ও রিকম্পোজিশনের সাধারণ নীতি সম্পর্কে ধারণা পাওয়া যায়।
Contact ক্লাস হল অপরিবর্তনীয় ডেটা ক্লাস। এর কারণ হল, এর সব
প্যারামিটার val কীওয়ার্ডের মাধ্যমে ডিফাইন করা প্রিমিটিভ। Contact-এর
ইনস্ট্যান্স তৈরি করার পরে, আপনি অবজেক্টের প্রপার্টির ভ্যালু পরিবর্তন করতে পারবেন না।
আপনি যদি এটি করার চেষ্টা করেন, তাহলে আপনি একটি নতুন অবজেক্ট তৈরি করবেন।
data class Contact(val name: String, val number: String)
ContactRow কম্পোজ করার উপযুক্ত আইটেমে Contact ধরনের প্যারামিটার আছে।
@Composable
fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {
var selected by remember { mutableStateOf(false) }
Row(modifier) {
ContactDetails(contact)
ToggleButton(selected, onToggled = { selected = !selected })
}
}
ব্যবহারকারী টগল বোতামে ক্লিক করলে এবং
selected স্ট্যাটাস পরিবর্তন হলে কী হয় তা বিবেচনা করুন:
- Compose,
ContactRow-এর মধ্যে থাকা কোড আবার কম্পোজ করা উচিত কিনা তা মূল্যায়ন করে। - এটি দেখে যে
ContactDetails-এর একমাত্র আর্গুমেন্টটিContactধরনের। Contactহল অপরিবর্তনীয় ডেটা ক্লাস, তাই Compose নিশ্চিত যেContactDetails-এর কোনও আর্গুমেন্ট পরিবর্তিত হয়নি।- তাই, কম্পোজ
ContactDetailsএড়িয়ে যায় এবং এটি আবার কম্পোজ করে না। - অন্যদিকে,
ToggleButton-এর আর্গুমেন্ট পরিবর্তন করা হয়েছে এবং Compose সেই কম্পোনেন্ট আবার কম্পোজ করে।
পরিবর্তনযোগ্য অবজেক্ট
পূর্ববর্তী উদাহরণে অপরিবর্তনীয় অবজেক্ট ব্যবহার করা হলেও, পরিবর্তনযোগ্য অবজেক্ট তৈরি করা সম্ভব। নিচের স্নিপেটটি দেখুন:
data class Contact(var name: String, var number: String)
Contact-এর প্রতিটি প্যারামিটার এখন var হওয়ায়, ক্লাস আর অপরিবর্তনীয় নেই।
এর প্রপার্টি পরিবর্তন হলে, Compose তা জানতে পারবে না। এর কারণ হল,
Compose শুধুমাত্র Compose State অবজেক্টে হওয়া পরিবর্তন ট্র্যাক করে।
Compose এই ধরনের ক্লাসকে অস্থির বলে বিবেচনা করে। স্ট্রং স্কিপিং মোড
(Kotlin 2.0.20+)-এর সাহায্যে, Compose ইনস্ট্যান্স ইকুয়ালিটি (===) ব্যবহার করে Contact তুলনা করে:
contact.name-এ ইন-প্লেস মিউটেশন হলে রিকম্পোজিশন ট্রিগার হবে না, তবে একই ভ্যালু সহ
নতুন করে অ্যালোকেট করা Contact ইনস্ট্যান্স পাস করলে, ContactDetails-কে রিকম্পোজ
করতে হবে (এবং স্ট্রং স্কিপিং মোড না থাকলে,
selected পরিবর্তন হলেই ContactDetails রিকম্পোজ হয়)।
Compose-এ প্রয়োগ করা
পুনঃসংযোজনের সময় কোন ফাংশন বাদ দিতে হবে তা Compose কীভাবে নির্ধারণ করে তা বিবেচনা করা সহায়ক হতে পারে, যদিও এটি অপরিহার্য নয়।
আপনার কোডে Compose কম্পাইলার রান করলে, এটি প্রতিটি ফাংশন ও টাইপকে একাধিক ট্যাগের মধ্যে একটি দিয়ে চিহ্নিত করে। রিকম্পোজিশনের সময় Compose কীভাবে ফাংশন বা টাইপ ম্যানেজ করে তা এইসব ট্যাগ থেকে বোঝা যায়।
অপেক্ষক
Compose ফাংশনকে skippable বা restartable হিসেবে চিহ্নিত করতে পারে। মনে রাখবেন, এটি কোনও ফাংশনকে
এগুলির মধ্যে একটি, দুটি বা কোনওটিই হিসেবে চিহ্নিত করতে পারে:
- এড়িয়ে যাওয়া যায়: কম্পাইলার কোনও কম্পোজ করার উপযুক্ত আইটেমকে এড়িয়ে যাওয়া যায় হিসেবে চিহ্নিত করলে, Compose সেটি আবার কম্পোজ করার সময় এড়িয়ে যেতে পারে, যদি এর সব আর্গুমেন্ট সেটির আগের মানের সমান হয়। (Kotlin 2.0.20+ ভার্সনে স্ট্রং স্কিপিং মোড থাকলে, সব পুনরায় চালু করা যায় এমন কম্পোজ করার মতো আইটেম অটোমেটিক স্কিপ করা যায়।)
- রিস্টার্ট করা যায়: রিস্টার্ট করা যায় এমন কম্পোজ করার উপযুক্ত আইটেম "স্কোপ" হিসেবে কাজ করে, যেখানে আবার কম্পোজ করা শুরু করা যায়। অন্যভাবে বলতে গেলে, ফাংশনটি এমন একটি পয়েন্ট হতে পারে যেখানে স্টেট পরিবর্তন হওয়ার পরে কম্পোজ আবার কোড এক্সিকিউট করা শুরু করতে পারে।
ধরন
কম্পোজ মার্কের ধরনকে অপরিবর্তনীয় বা স্থিতিশীল হিসেবে চিহ্নিত করুন। প্রতিটি ধরন এক বা অন্য কিছু:
- পরিবর্তনযোগ্য নয়: Compose কোনও ধরনের প্রপার্টির ভ্যালু
কখনও পরিবর্তন করা না গেলে এবং সমস্ত পদ্ধতি রেফারেন্সের দিক থেকে স্বচ্ছ হলে, সেটিকে পরিবর্তনযোগ্য নয় হিসেবে চিহ্নিত করে।
- মনে রাখবেন, সব আদিম টাইপকে অপরিবর্তনীয় হিসেবে চিহ্নিত করা হয়। এর মধ্যে
String,IntওFloatঅন্তর্ভুক্ত।
- মনে রাখবেন, সব আদিম টাইপকে অপরিবর্তনীয় হিসেবে চিহ্নিত করা হয়। এর মধ্যে
- স্টেবল: এমন ধরনের কথা বলে যার প্রপার্টি তৈরি হওয়ার পরে পরিবর্তন করা যেতে পারে। রানটাইম চলাকালীন সেইসব প্রপার্টি পরিবর্তন করা হলে, Compose সেইসব পরিবর্তন সম্পর্কে অবগত হয়।
ডিবাগ স্থিতিশীলতা
আপনার অ্যাপ যদি এমন কোনও কম্পোজ করার মতো আইটেম আবার কম্পোজ করে যার প্যারামিটার পরিবর্তন হয়নি, তাহলে প্রথমে
চেক করুন যে প্রতিটি
আবার কম্পোজ করার সময় আনস্টেবল ধরনের নতুন ইনস্ট্যান্স অ্যাসাইন করা হচ্ছে কিনা (অথবা, স্ট্রং স্কিপিং মোড বন্ধ করা থাকলে, কম্পোজ করার মতো আইটেমে
var প্রপার্টি বা আনস্টেবল ধরনের val প্রপার্টি আছে কিনা)।
Compose-এ স্থিতিশীলতা সংক্রান্ত জটিল সমস্যা কীভাবে নির্ণয় করবেন সেই সম্পর্কে বিস্তারিত তথ্য পেতে, স্থিতিশীলতা ডিবাগ করা গাইড দেখুন।
স্থিতিশীলতা সংক্রান্ত সমস্যার সমাধান করা
আপনার Compose প্রয়োগে কীভাবে স্থিতিশীলতা আনবেন সেই সম্পর্কে তথ্য পেতে, স্থিতিশীলতা সংক্রান্ত সমস্যার সমাধান করুন গাইড দেখুন।
সারাংশ
মোটকথা, আপনাকে নিম্নলিখিত বিষয়গুলি মনে রাখতে হবে:
- প্যারামিটার: রিকম্পোজিশনের সময় স্ট্রাকচারাল ইকুয়ালিটি
(
.equals()) বা ইনস্ট্যান্স ইকুয়ালিটি (===) ব্যবহার করে কম্পেয়ার করা হবে কিনা তা নির্ধারণ করতে, Compose আপনার কম্পোজেবল প্যারামিটারের স্থিতিশীলতা নির্ধারণ করে। - অবিলম্বে সমাধান: আপনি যদি লক্ষ্য করেন যে আপনার কম্পোজ করার উপযুক্ত আইটেম এড়িয়ে যাওয়া হচ্ছে না এবং
এর ফলে পারফর্ম্যান্স সংক্রান্ত সমস্যা হচ্ছে, তাহলে চেক করে দেখুন যে প্রতিটি পাসে অস্থির
প্যারামিটারের নতুন ইনস্ট্যান্স আবার তৈরি করা হচ্ছে কিনা অথবা
State-এর পরিবর্তেvarপ্রপার্টি ব্যবহার করা হচ্ছে কিনা। - কম্পাইলার রিপোর্ট: আপনার ক্লাস সম্পর্কে কী ধরনের স্থিতিশীলতা অনুমান করা হচ্ছে তা নির্ধারণ করতে, আপনি কম্পাইলার রিপোর্ট ব্যবহার করতে পারেন।
- সংগ্রহ: কম্পোজ স্ট্যান্ডার্ড সংগ্রহ ইন্টারফেস (
List,SetএবংMap)-কে আনস্টেবল হিসেবে বিবেচনা করে কারণ এগুলির অন্তর্নিহিত প্রয়োগগুলি পরিবর্তনযোগ্য হতে পারে। স্ট্রং স্কিপিং মোড (Kotlin 2.0.20+ ভার্সনে ডিফল্ট হিসেবে চালু থাকে) ব্যবহার করলে, কালেকশন রেফারেন্স পরিবর্তন না হলে, আনস্টেবল কালেকশন এখনও দ্রুতO(1)ইনস্ট্যান্স ইকুয়ালিটি (===) ব্যবহার করে রিকম্পোজিশন স্কিপ করে। Kotlinx অপরিবর্তনীয় কালেকশন বা@Immutableবা@Stableসহ কালেকশন-হোল্ডিং ক্লাসকে অ্যানোটেট করার জন্য বড় কালেকশন কনভার্ট করা এড়িয়ে চলুন, যদি না স্ট্রাকচারাল ইকুয়ালিটি (O(N).equals()) বিশেষভাবে প্রয়োজন হয়, কারণ প্রতিটি রিকম্পোজিশনে প্রতিটি এলিমেন্ট তুলনা করা রিকম্পোজিশনের চেয়ে বেশি ব্যয়বহুল হতে পারে। - অন্যান্য মডিউল: Compose, কম্পাইলার না চালানো মডিউল থেকে ক্লাসকে অস্থির বলে মনে করে (
===ব্যবহার করে তুলনা করা হয়, যা স্ট্রং স্কিপিং মোডের অধীনে করা হয়)। কোনও ডেটা সোর্স যদি প্রায়ই একই ভ্যালু সহ নন-Compose মডিউল থেকে ছোট, ফ্ল্যাট মডেল আবার ইনস্ট্যানশিয়েট করে, তাহলে আপনি একটি স্টেবিলিটি কনফিগারেশন ফাইল কনফিগার করতে পারেন অথবা@Stableবা@Immutableব্যবহার করতে পারেন, যেখানে.equals()হল সস্তা।
আরও পড়ুন
- পারফর্ম্যান্স: Compose পারফর্ম্যান্স সংক্রান্ত আরও ডিবাগিং পরামর্শ পেতে, আমাদের পেশাদার পদ্ধতির গাইড ও I/O টক দেখুন।