এই পৃষ্ঠায়, আপনি কম্পোজ করার উপযুক্ত আইটেমের লাইফসাইকেল এবং কোনও কম্পোজ করার উপযুক্ত আইটেমকে আবার কম্পোজ করার প্রয়োজন আছে কিনা তা Compose কীভাবে নির্ধারণ করে সেই সম্পর্কে জানবেন।
লাইফসাইকেল ওভারভিউ
ম্যানেজিং স্টেট ডকুমেন্টেশনে উল্লেখ করা হয়েছে যে, একটি কম্পোজিশন আপনার অ্যাপের UI বর্ণনা করে এবং কম্পোজ করার উপযুক্ত আইটেম রান করানোর মাধ্যমে এটি তৈরি করা হয়। কম্পোজিশন হল কম্পোজ করার উপযুক্ত আইটেমের ট্রি-স্ট্রাকচার যা আপনার UI বর্ণনা করে।
Jetpack Compose প্রথমবার আপনার কম্পোজ করার মতো আইটেম রান করালে, প্রাথমিক কম্পোজিশন চলাকালীন, এটি সেইসব কম্পোজ করার মতো আইটেমের ট্র্যাক রাখবে যেগুলি আপনি কোনও কম্পোজিশনে আপনার UI বর্ণনা করার জন্য কল করেন। তারপরে, আপনার অ্যাপের স্টেট পরিবর্তন হলে, Jetpack Compose একটি রিকম্পোজিশন শিডিউল করে। রিকম্পোজিশন হল যখন Jetpack Compose স্টেটে হওয়া পরিবর্তনের ফলে পরিবর্তিত হতে পারে এমন কম্পোজ করার উপযুক্ত আইটেমকে আবার এক্সিকিউট করে, এবং তারপর কোনও পরিবর্তন হলে তা দেখানোর জন্য কম্পোজিশন আপডেট করে।
কোনও কম্পোজিশন শুধুমাত্র প্রাথমিক কম্পোজিশন থেকে তৈরি করা যায় এবং রিকম্পোজিশনের মাধ্যমে আপডেট করা যায়। কম্পোজিশন পরিবর্তন করার একমাত্র উপায় হল রিকম্পোজিশন।
সাধারণত, কোনও
State<T> অবজেক্টে পরিবর্তন হলে রিকম্পোজিশন ট্রিগার হয়। Compose
এগুলি ট্র্যাক করে এবং কম্পোজিশনে থাকা সেইসব কম্পোজ করার উপযুক্ত আইটেম রান করায় যেগুলি সেই
নির্দিষ্ট State<T> পড়ে এবং সেইসব কম্পোজ করার উপযুক্ত আইটেমকে কল করে যেগুলি
এড়িয়ে যাওয়া যায় না।
কোনও কম্পোজ করার উপযুক্ত আইটেম একাধিকবার কল করা হলে, একাধিক ইনস্ট্যান্স কম্পোজিশনে প্লেস করা হয়। কম্পোজিশনে প্রতিটি কলের নিজস্ব লাইফ-সাইকেল থাকে।
@Composable fun MyComposable() { Column { Text("Hello") Text("World") } }
MyComposable-এর উপস্থাপনা। কোনও
কম্পোজ করার মতো আইটেম একাধিকবার কল করা হলে, একাধিক ইনস্ট্যান্স
কম্পোজিশনে প্লেস করা হয়। কোনও এলিমেন্টের রঙ আলাদা হলে বুঝতে হবে যে এটি একটি
আলাদা ইনস্ট্যান্স।কম্পোজিশনে কম্পোজ করার উপযুক্ত আইটেমের গঠন
কম্পোজিশনে কম্পোজ করার উপযুক্ত আইটেমের ইনস্ট্যান্সকে এর কল সাইট দ্বারা শনাক্ত করা হয়। Compose কম্পাইলার প্রতিটি কল সাইটকে আলাদা আলাদা হিসেবে বিবেচনা করে। একাধিক কল সাইট থেকে কল করা কম্পোজ করার মতো আইটেম কম্পোজিশনে কম্পোজ করার মতো আইটেমের একাধিক ইনস্ট্যান্স তৈরি করবে।
রিকম্পোজিশনের সময়, কম্পোজ করার মতো কোনও আইটেম যদি আগের কম্পোজিশনের সময় কল করা হয়নি এমন কোনও আইটেমকে কল করে, তাহলে Compose কোন কোন কম্পোজ করার মতো আইটেমকে কল করা হয়েছে বা হয়নি তা শনাক্ত করবে এবং যেসব কম্পোজ করার মতো আইটেমকে দুটি কম্পোজিশনেই কল করা হয়েছে, Compose সেগুলির ইনপুট পরিবর্তন না হলে, সেগুলিকে আবার কম্পোজ করা এড়িয়ে যাবে।
কম্পোজ করা যায় এমন উপাদানের সাথে পার্শ্বপ্রতিক্রিয়াকে যুক্ত করার জন্য পরিচয় রক্ষা করা অত্যন্ত গুরুত্বপূর্ণ, যাতে প্রতিটি রিকম্পোজিশনের জন্য রিস্টার্ট করার পরিবর্তে সেগুলি সফলভাবে সম্পূর্ণ হতে পারে।
নিম্নলিখিত উদাহরণ বিবেচনা করে দেখুন:
@Composable fun LoginScreen(showError: Boolean) { if (showError) { LoginError() } LoginInput() // This call site affects where LoginInput is placed in Composition } @Composable fun LoginInput() { /* ... */ } @Composable fun LoginError() { /* ... */ }
উপরের কোড স্নিপেটে, LoginScreen কন্ডিশনালি
LoginError কম্পোজ করার উপযুক্ত ফাংশনকে কল করবে এবং সবসময় LoginInput কম্পোজ করার উপযুক্ত ফাংশনকে কল করবে। প্রতিটি
কলের একটি অনন্য কল সাইট ও সোর্স পজিশন থাকে, যা কম্পাইলার এটিকে
অনন্যভাবে শনাক্ত করতে ব্যবহার করবে।
LoginScreen-এর
প্রতিনিধিত্ব। একই রঙ মানে এটি আবার কম্পোজ করা হয়নি।LoginInput-কে আগে কল করা থেকে দ্বিতীয়বার কল করা হলেও,
রীকম্পোজিশন জুড়ে LoginInput ইনস্ট্যান্স সংরক্ষিত থাকবে। এছাড়াও,
LoginInput-এর কোনও প্যারামিটার নেই যা রিকম্পোজিশন জুড়ে
পরিবর্তিত হয়েছে, তাই Compose LoginInput-এ কল করা এড়িয়ে যাবে।
স্মার্ট রিকম্পোজিশনকে সাহায্য করতে অতিরিক্ত তথ্য যোগ করা
কম্পোজেবলকে একাধিকবার কল করলে, এটি কম্পোজিশনেও একাধিকবার যোগ হবে। একই কল সাইট থেকে কোনও কম্পোজ করার উপযুক্ত আইটেম একাধিকবার কল করা হলে, Compose-এর কাছে সেই কম্পোজ করার উপযুক্ত আইটেমকে স্বতন্ত্রভাবে শনাক্ত করার কোনও তথ্য থাকে না, তাই ইনস্ট্যান্সগুলিকে আলাদা আলাদা করে রাখার জন্য কল সাইটের পাশাপাশি এক্সিকিউশন অর্ডারও ব্যবহার করা হয়। এই আচরণ কখনও কখনও যথেষ্ট হলেও, কিছু ক্ষেত্রে এটি অবাঞ্ছিত আচরণ করতে পারে।
@Composable fun MoviesScreen(movies: List<Movie>) { Column { for (movie in movies) { // MovieOverview composables are placed in Composition given its // index position in the for loop MovieOverview(movie) } } }
উপরের উদাহরণে, কম্পোজ কল
সাইট ছাড়াও এক্সিকিউশন অর্ডার ব্যবহার করে যাতে কম্পোজিশনে ইনস্ট্যান্স আলাদা আলাদা থাকে। তালিকার নিচে কোনও নতুন movie যোগ করা হলে
কম্পোজ টুলকিট, কম্পোজিশনে আগে থেকেই থাকা ইনস্ট্যান্স আবার ব্যবহার করতে পারে, কারণ তালিকায় তাদের লোকেশন পরিবর্তন হয়নি এবং সেইজন্য, সেইসব ইনস্ট্যান্সের জন্য
movie ইনপুট একই থাকে।
MoviesScreen-এর উপস্থাপনা। MovieOverview কম্পোজিশনের মধ্যে থাকা
কম্পোজেবল আবার ব্যবহার করা যেতে পারে। MovieOverview-এ একই রঙ থাকার অর্থ হল, কম্পোজ করার উপযুক্ত
আইটেমটি আবার কম্পোজ করা হয়নি।তবে, movies তালিকায় আইটেম যোগ করে উপরে বা
মাঝখানে, আইটেম সরিয়ে বা আবার সাজিয়ে তালিকা পরিবর্তন করা হলে, এর ফলে সব MovieOverview কলে আবার কম্পোজিশন
হবে, যেগুলির ইনপুট প্যারামিটার তালিকায়
অবস্থান পরিবর্তন করেছে। এটি অত্যন্ত গুরুত্বপূর্ণ যদি, উদাহরণস্বরূপ, MovieOverview কোনও সাইড এফেক্ট ব্যবহার করে
সিনেমার ছবি ফেচ করে। এফেক্ট প্রয়োগ করার প্রসেস চলাকালীন
রিমিক্স করা হলে, সেটি বাতিল হয়ে যাবে এবং আবার শুরু হবে।
@Composable fun MovieOverview(movie: Movie) { Column { // Side effect explained later in the docs. If MovieOverview // recomposes, while fetching the image is in progress, // it is cancelled and restarted. val image = loadNetworkImage(movie.url) MovieHeader(image) /* ... */ } }
MoviesScreen-এর উপস্থাপনা। MovieOverview কম্পোজ করার উপযুক্ত আইটেম আবার ব্যবহার করা যাবে না এবং
সব সাইড এফেক্ট আবার শুরু হবে। MovieOverview-এ অন্য রঙ মানে হল
কম্পোজ করার উপযুক্ত আইটেম আবার কম্পোজ করা হয়েছে।আদর্শভাবে, আমরা MovieOverview ইনস্ট্যান্সের পরিচয়কে
movie-এর পরিচয়ের সাথে লিঙ্ক করা হিসেবে দেখতে চাই যা এতে পাস করা হয়। সিনেমাগুলির
তালিকা নতুন করে সাজালে, আদর্শভাবে আমরা প্রতিটি MovieOverview কম্পোজ করার পরিবর্তে
কম্পোজিশন ট্রি-তে থাকা ইনস্ট্যান্সগুলিকেও একইভাবে নতুন করে সাজাব। Compose আপনাকে রানটাইমকে
বলার একটি উপায় প্রদান করে যে আপনি ট্রিয়ের কোনও নির্দিষ্ট অংশ শনাক্ত করতে কোন মান ব্যবহার করতে চান: কম্পোজ করার
key
যোগ্য।
এক বা একাধিক ভ্যালু পাস করা কী কম্পোজ করার উপযুক্ত আইটেমের কলে কোডের একটি ব্লক র্যাপ করার মাধ্যমে, সেইসব ভ্যালুকে কম্পোজিশনে সেই
ইনস্ট্যান্স শনাক্ত করার জন্য ব্যবহার করতে একত্রিত করা হবে।
key-এর ভ্যালু
গ্লোবালি অনন্য হওয়ার প্রয়োজন নেই, এটি শুধুমাত্র কল সাইটে কম্পোজ করার মতো
ইনভোকেশনের মধ্যে অনন্য হতে হবে। তাই এই উদাহরণে, প্রতিটি movie-এর একটি
key থাকতে হবে যা movies-এর মধ্যে অনন্য; এটি সেই key-কে
অ্যাপের অন্য কোথাও কিছু কম্পোজ করার সাথে শেয়ার করলে কোনও সমস্যা নেই।
@Composable fun MoviesScreenWithKey(movies: List<Movie>) { Column { for (movie in movies) { key(movie.id) { // Unique ID for this movie MovieOverview(movie) } } } }
উপরের তথ্য অনুযায়ী, তালিকায় থাকা এলিমেন্ট পরিবর্তন হলেও, কম্পোজ MovieOverview-এ করা
আলাদা আলাদা কল শনাক্ত করতে পারে এবং সেগুলি আবার ব্যবহার করতে পারে।
MoviesScreen-এর উপস্থাপনা। MovieOverview কম্পোজ করার যোগ্য আইটেমের অনন্য
কী থাকার কারণে, Compose বুঝতে পারে যে কোন MovieOverview ইনস্ট্যান্স পরিবর্তন করা হয়নি এবং
সেগুলি আবার ব্যবহার করতে পারে; সেগুলির সাইড এফেক্ট এক্সিকিউট করা চালিয়ে যাবে।কিছু কম্পোজ করার উপযুক্ত আইটেমে key কম্পোজ করার উপযুক্ত আইটেমের জন্য বিল্ট-ইন সহায়তা থাকে। যেমন,
items DSL-এ key কাস্টমাইজ করার সুবিধা LazyColumn গ্রহণ করে।
@Composable fun MoviesScreenLazy(movies: List<Movie>) { LazyColumn { items(movies, key = { movie -> movie.id }) { movie -> MovieOverview(movie) } } }
ইনপুট পরিবর্তন না হলে স্কিপ করা
রিকম্পোজিশনের সময়, কিছু উপযুক্ত কম্পোজ করার মতো ফাংশনের এক্সিকিউশন সম্পূর্ণভাবে এড়িয়ে যাওয়া হতে পারে, যদি তাদের ইনপুট আগের কম্পোজিশনের থেকে পরিবর্তিত না হয়ে থাকে।
কম্পোজেবল ফাংশন এড়িয়ে যাওয়ার উপযুক্ত যদি না:
- ফাংশনের রিটার্ন টাইপ
Unitনয় - ফাংশনটি
@NonRestartableComposableবা@NonSkippableComposableদিয়ে অ্যানোটেট করা হয়েছে - প্রয়োজনীয় প্যারামিটারটি নন-স্টেবল ধরনের
একটি কম্পাইলার মোড আছে, স্ট্রং স্কিপিং, যা শেষ প্রয়োজনীয়তা শিথিল করে।
কোনও টাইপকে স্থিতিশীল হিসেবে বিবেচনা করতে হলে, সেটিকে নিম্নলিখিত কন্ট্যাক্ট মেনে চলতে হবে:
- দুটি ইনস্ট্যান্সের জন্য
equals-এর ফলাফল চিরকাল একই দুটি ইনস্ট্যান্সের জন্য একই হবে। - কোনও পাবলিক প্রপার্টির ধরন পরিবর্তন হলে, কম্পোজিশনকে বিজ্ঞপ্তি পাঠানো হবে।
- এছাড়াও, সব ধরনের পাবলিক প্রপার্টি স্থিতিশীল।
এই চুক্তির আওতায় কিছু গুরুত্বপূর্ণ সাধারণ ধরন পড়ে যেগুলিকে
Compose কম্পাইলার স্থিতিশীল হিসেবে বিবেচনা করবে, যদিও @Stableঅ্যানোটেশন ব্যবহার করে সেগুলিকে স্পষ্টভাবে স্থিতিশীল হিসেবে
চিহ্নিত করা হয়নি:
- সব আদিম ভ্যালু টাইপ:
Boolean,Int,Long,Float,Char, ইত্যাদি। - স্ট্রিং
- সব ধরনের ফাংশন (ল্যাম্বডা)
এইসব ধরনের সবকটিই স্টেবল ভার্সনের কন্ট্র্যাক্ট মেনে চলতে পারে কারণ সেগুলি পরিবর্তনযোগ্য নয়। যেহেতু অপরিবর্তনীয় টাইপ কখনও পরিবর্তন হয় না, তাই সেগুলিকে কখনও পরিবর্তনের কম্পোজিশন সম্পর্কে বিজ্ঞপ্তি দিতে হয় না, তাই এই চুক্তি মেনে চলা অনেক সহজ।
একটি উল্লেখযোগ্য ধরন যা স্থিতিশীল কিন্তু পরিবর্তনযোগ্য তা হল Compose-এর MutableState
টাইপ। কোনও ভ্যালু MutableState-এ হোল্ড করা থাকলে, সামগ্রিকভাবে স্টেট অবজেক্টকে
স্থিতিশীল হিসেবে বিবেচনা করা হয়, কারণ Compose-কে State-এর
.value প্রপার্টিতে হওয়া যেকোনও পরিবর্তন সম্পর্কে বিজ্ঞপ্তি পাঠানো হবে।
কোনও কম্পোজ করার উপযুক্ত আইটেমে প্যারামিটার হিসেবে পাস করা সব ধরনের আইটেম স্থিতিশীল হলে, UI ট্রি-তে কম্পোজ করার উপযুক্ত আইটেমের পজিশনের উপর ভিত্তি করে প্যারামিটার ভ্যালু সমান কিনা তা তুলনা করে দেখা হয়। আগের কল থেকে সব ভ্যালু অপরিবর্তিত থাকলে, রিকম্পোজিশন এড়িয়ে যাওয়া হয়।
Compose কোনও টাইপকে তখনই স্থিতিশীল হিসেবে বিবেচনা করে যদি সেটি প্রমাণ করা যায়। যেমন, কোনও ইন্টারফেসকে সাধারণত স্থিতিশীল হিসেবে বিবেচনা করা হয় না এবং পরিবর্তনযোগ্য পাবলিক প্রপার্টি সহ এমন ধরনের আইটেম যার ইমপ্লিমেন্টেশন অপরিবর্তনযোগ্য হতে পারে, সেগুলিও স্থিতিশীল নয়।
Compose যদি বুঝতে না পারে যে কোনও ধরন স্থিতিশীল, কিন্তু আপনি যদি Compose-কে
জোর করে স্থিতিশীল হিসেবে ট্রিট করতে চান, তাহলে এটিকে
@Stable অ্যানোটেশন দিয়ে চিহ্নিত করুন।
// Marking the type as stable to favor skipping and smart recompositions. @Stable interface UiState<T : Result<T>> { val value: T? val exception: Throwable? val hasError: Boolean get() = exception != null }
উপরের কোড স্নিপেটে, যেহেতু UiState হল একটি ইন্টারফেস, তাই Compose সাধারণত
এই ধরনের কোডকে স্থিতিশীল হিসেবে বিবেচনা নাও করতে পারে। @Stable
অ্যানোটেশন যোগ করার মাধ্যমে, আপনি Compose-কে জানান যে এই ধরনের ভ্যালু স্থিতিশীল, এর ফলে Compose
স্মার্ট রিকম্পোজিশনকে অগ্রাধিকার দিতে পারে। এর অর্থ হল, ইন্টারফেসকে প্যারামিটার টাইপ হিসেবে ব্যবহার করা হলে, Compose-এর সমস্ত
ইমপ্লিমেন্টেশনকে স্থিতিশীল হিসেবে বিবেচনা করা হবে।
আপনার জন্য সাজেস্ট করা হয়েছে
- মনে রাখবেন: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট দেখানো হয়
- State ও Jetpack Compose
- Compose-এ সাইড-ইফেক্ট
- Compose-এ UI স্টেট সেভ করা