Composition হল Jetpack Compose-এর কেন্দ্রীয় প্রক্রিয়া, যার সময় বর্ণনামূলক Composable ফাংশন থেকে স্ক্রিনে প্রদর্শিত একটি জীবন্ত UI ট্রি তৈরি করা হয়। Android View সিস্টেমের বিপরীতে, যেখানে XML থেকে লেআউট লোড করে অপরিবর্তনীয় অবজেক্টে রূপান্তরিত করা হত, Composition একটি গতিশীল সিস্টেম হিসেবে কাজ করে: ফাংশনগুলি কার্যকর হয়, মেমরিতে স্লট তৈরি করে, নোডের একটি শ্রেণিবিন্যাস গঠন করে এবং এটিকে অবস্থার সাথে আবদ্ধ করে। Google Android Developers, 2026 অনুসারে, Compose অ্যাপ্লিকেশনের কর্মক্ষমতা অপ্টিমাইজ করার জন্য Composition বোঝা গুরুত্বপূর্ণ।
মূল বিষয়
Composition হল Composable ফাংশন কার্যকর করার প্রক্রিয়া, যার ফলস্বরূপ নোডের একটি ট্রি হিসেবে ব্যবহারকারী ইন্টারফেসের অভ্যন্তরীণ উপস্থাপনা তৈরি হয়। এই ট্রির প্রতিটি নোড হয় একটি অন্তর্নির্মিত উপাদান (Text, Button, Image) অথবা একটি ব্যবহারকারী-সংজ্ঞায়িত Composable ফাংশনের কলের সাথে মিলে যায়। Composition সরাসরি Android View অবজেক্ট তৈরি করে না — এটি একটি বিমূর্ত বিবরণ তৈরি করে যা পরে Layout এবং Drawing পর্যায় দ্বারা প্রক্রিয়াকৃত হয়।
Composition-এর মূল বৈশিষ্ট্য হল এর পুনরায় আরম্ভযোগ্যতা। কম্পোজিশনের মধ্যে প্রতিটি Composable ফাংশন যেকোনো সময় পুনরায় আরম্ভ করা যেতে পারে যদি এর ইনপুট প্যারামিটার বা এটি পড়া অবস্থার অবজেক্ট পরিবর্তিত হয়। সিস্টেম পুরো ট্রি পুনরায় আরম্ভ করে না — শুধুমাত্র সেই ফাংশনগুলি যা প্রকৃতপক্ষে পরিবর্তিত ডেটার উপর নির্ভরশীল।
প্রযুক্তিগতভাবে, Composition Composer-এর মাধ্যমে পরিচালিত হয় — একটি অভ্যন্তরীণ ইঞ্জিন যা Kotlin কম্পাইলার প্রতিটি Composable ফাংশনে এম্বেড করে। Composer স্লটে (অবস্থান গোষ্ঠী) তথ্য লেখে কোন ফাংশনগুলি কল করা হয়েছে, কী প্যারামিটার সহ এবং কী ক্রমে। পরবর্তী কলগুলিতে, Composer নতুন ডেটার সাথে সংরক্ষিত ডেটার তুলনা করে এবং পুনরায় আরম্ভ করার সিদ্ধান্ত নেয়।
UI ট্রি তৈরির প্রক্রিয়া শুরু হয় Activity বা Fragment-এর ভিতরে setContent পদ্ধতি কল করার মাধ্যমে। এই পদ্ধতি প্রাথমিক Composition তৈরি করে এবং রুট Composable ফাংশন কার্যকর করা শুরু করে। তারপর প্রতিটি নেস্টেড Composable ফাংশন ট্রিতে তার নোড যোগ করে, একটি শ্রেণিবিন্যাস গঠন করে: Row-এ Text এবং Button থাকে, Column-এ Image এবং Card থাকে, এবং এভাবেই চলতে থাকে।
প্রতিটি ট্রি নোড সোর্স কোডে তার অবস্থানের উপর ভিত্তি করে একটি অনন্য অবস্থান কী পায়। এই কীটি পরবর্তী কার্যকরীকরণের সময় নোড সনাক্ত করতে ব্যবহৃত হয়। অবস্থান কী হল কারণ কেন Composable ফাংশন কল করার ক্রম শর্তের উপর নির্ভর করা উচিত নয়: যদি একটি রানে A -> B কল করা হয়, এবং পরবর্তীতে B -> A, তাহলে Compose পুরানো এবং নতুন নোড মেলাতে পারবে না।
@Composable
fun AppScreen() {
Column { // Column নোড (অবস্থান 1)
HeaderSection() // HeaderSection নোড (অবস্থান 2)
ContentSection() // ContentSection নোড (অবস্থান 3)
FooterSection() // FooterSection নোড (অবস্থান 4)
}
}
@Composable
fun HeaderSection() {
Row { // Row নোড (অবস্থান 2.1)
Text("শিরোনাম") // Text নোড (অবস্থান 2.2)
Icon(...) // Icon নোড (অবস্থান 2.3)
}
}
এই উদাহরণে, প্রতিটি কল কোডের ক্রমের উপর ভিত্তি করে একটি অবস্থান পায়। Column (অবস্থান 1) তিনটি চাইল্ড নোড ধারণ করে (অবস্থান 2, 3, 4)। HeaderSection আরও দুটি চাইল্ড নোড যোগ করে (2.1, 2.2, 2.3)। যদি পরবর্তী পুনঃসংকলনে ContentSection HeaderSection-এর আগে কল করা হয়, তাহলে Composer সঠিকভাবে নোড মেলাতে পারবে না — তাই নিয়ম: Composable ফাংশন কলের ক্রম স্থিতিশীল হতে হবে।
Composition-এ অবস্থা State<T> টাইপের অবজেক্টের মাধ্যমে পরিচালিত হয়। যখন একটি Composable ফাংশন প্রতিনিধিত্বকারী বৈশিষ্ট্য (by) এর মাধ্যমে State থেকে মান পড়ে, তখন এটি সেই State-এর উপর নির্ভরশীলতা নিবন্ধন করে। যখন মান পরিবর্তিত হয়, এই State পড়া সমস্ত ফাংশন পরবর্তী কম্পোজিশন পর্যায়ে পুনরায় আরম্ভের জন্য চিহ্নিত হয়।
নির্ভরশীলতা নিবন্ধন প্রক্রিয়াকে snapshot সিস্টেম বলা হয়। প্রতিবার State পরিবর্তিত হলে, একটি snapshot সমস্ত পরিবর্তন রেকর্ড করে এবং Composer-কে জানায় কোন ফাংশনগুলি সেই State-এর উপর নির্ভরশীল। এটি বোঝা গুরুত্বপূর্ণ: নন-Composable কোডের ভিতরে (যেমন, onClick ল্যাম্বডায়) State পড়া নির্ভরশীলতা নিবন্ধন করে না — শুধুমাত্র Composable ফাংশনের ভিতরে বা কম্পোজিশন প্রসঙ্গে কার্যকর ল্যাম্বডায় পড়া।
Snapshot সিস্টেম লেনদেনভিত্তিকভাবে কাজ করে: একটি একক ইভেন্টের মধ্যে একাধিক State পরিবর্তন একটি লেনদেনে একত্রিত হয়, যা একাধিক পুনঃসংকলন প্রতিরোধ করে। এটি বিশেষ করে গুরুত্বপূর্ণ যখন অঙ্গভঙ্গি পরিচালনা করা হয়: একটি নড়াচড়া বেশ কয়েকটি State অবজেক্ট পরিবর্তন করে, কিন্তু Compose শুধুমাত্র একটি পুনঃসংকলন সম্পাদন করে।
@Composable
fun StateExample() {
var text by remember { mutableStateOf("Hello") }
var isVisible by remember { mutableStateOf(true) }
Column {
Text(text) // টেক্সট-এর উপর নির্ভরশীলতা নিবন্ধন করে
if (isVisible) { // isVisible-এর উপর নির্ভরশীলতা নিবন্ধন করে
TextField(value = text, onValueChange = { text = it })
}
Button(onClick = { isVisible = !isVisible }) {
Text(if (isVisible) "লুকান" else "দেখান")
}
}
}
টেক্সট পরিবর্তন শুধুমাত্র Column, Text এবং TextField-এর পুনঃসংকলন ঘটায়। Column, Button এবং isVisible শর্ত অপরিবর্তিত থাকে। পুনঃসংকলনের এই বিচ্ছিন্নতা হল Compose-এর একটি মূল সুবিধা সেই সিস্টেমগুলির তুলনায় যা পুরো স্ক্রিন পুনরায় আঁকে। প্রতিটি Composable ফাংশন শুধুমাত্র সেই State অবজেক্টগুলি ট্র্যাক করে যা এটি সরাসরি পড়ে।
Composition এবং Recomposition হল Composable ফাংশন কার্যকর করার দুটি ভিন্ন মোড। Composition স্ক্রিন তৈরি হলে একবার ঘটে: সিস্টেম প্রাথমিক মান সহ সমস্ত Composable ফাংশন কার্যকর করে এবং প্রাথমিক UI ট্রি তৈরি করে। Recomposition ডেটা পরিবর্তিত হলে একাধিকবার ঘটে: সিস্টেম শুধুমাত্র সেই ফাংশনগুলি পুনরায় আরম্ভ করে যা পরিবর্তিত অবস্থার উপর নির্ভরশীল।
মোড Composition সমস্ত ট্রি নোড সক্রিয় করে, প্রতিটি ফাংশনের জন্য স্লট বরাদ্দ করে এবং সমস্ত বংশধর নিবন্ধন করে। Recomposition নির্বাচনীভাবে কাজ করে: Compose প্রতিটি ফাংশনের নতুন এবং পুরানো প্যারামিটার মান তুলনা করে, এবং যদি সেগুলি পরিবর্তিত না হয় — ফাংশনটি কার্যকর হয় না (skipping)।
Composition এবং Recomposition ব্যয়ে ভিন্ন। প্রথম Composition বেশি ব্যয়বহুল কারণ এতে সম্পূর্ণ ট্রি নির্মাণ এবং স্লট বরাদ্দ প্রয়োজন। Recomposition সস্তা, বিশেষ করে যদি বেশিরভাগ ফাংশন স্থিতিশীল হয় — তাদের প্যারামিটার equals দ্বারা তুলনা করা হয়, এবং Compose তাদের আহ্বান এড়িয়ে যায়। সর্বোচ্চ কর্মক্ষমতার জন্য, আপনার চেষ্টা করা উচিত যে বেশিরভাগ পুনঃসংকলন যতটা সম্ভব কম ফাংশনকে প্রভাবিত করে।
| বৈশিষ্ট্য | Composition | Recomposition |
|---|---|---|
| কখন ঘটে | একবার, প্রথম প্রদর্শনে | একাধিকবার, ডেটা পরিবর্তনে |
| পরিধি | সম্পূর্ণ ট্রি | শুধুমাত্র পরিবর্তিত ফাংশন |
| প্যারামিটার তুলনা | করা হয় না | এড়িয়ে যাওয়ার জন্য করা হয় |
| স্লট তৈরি | হ্যাঁ, সব স্লট তৈরি হয় | শুধুমাত্র নতুন নোডের জন্য |
CompositionLocal হল কম্পোজিশন ট্রির মাধ্যমে নিহিতভাবে ডেটা পাঠানোর একটি প্রক্রিয়া। এটি সমস্যার সমাধান করে যখন একটি প্যারামিটারকে ডজনখানেক নেস্টেড Composable ফাংশনের মাধ্যমে পাঠানোর প্রয়োজন হয় যা এটি সরাসরি ব্যবহার করে না। স্পষ্ট প্যারামিটার চেইনের পরিবর্তে, ডেটা শীর্ষ স্তরে সেট করা হয় এবং CompositionLocal.current-এর মাধ্যমে যেকোনো নেস্টেড ফাংশনে পড়া হয়।
MaterialTheme হল CompositionLocal-এর সবচেয়ে পরিচিত উদাহরণ। সমস্ত Compose উপাদান MaterialTheme.colorScheme, MaterialTheme.typography, MaterialTheme.shapes-এর মাধ্যমে রং, টাইপোগ্রাফি এবং আকার পড়ে, প্যারামিটার মাধ্যমে না পেয়ে। ডেভেলপাররা বর্তমান ব্যবহারকারী, স্থানীয়করণ সেটিংস বা স্ক্রিন কনফিগারেশনের মতো ডেটার জন্য নিজস্ব CompositionLocal তৈরি করতে পারেন।
একটি গুরুত্বপূর্ণ সীমাবদ্ধতা: CompositionLocal প্রায়শই পরিবর্তিত ডেটার (স্ক্রোল অবস্থান, ইনপুট ফিল্ডের টেক্সট) জন্য ব্যবহার করা উচিত নয়। একটি উপাদান যা CompositionLocal পড়ে তা প্রতি বার মান পরিবর্তিত হলে পুনরায় আরম্ভ হয়, তাই গতিশীল ডেটার জন্য স্পষ্ট প্যারামিটার বা State ব্যবহার করা ভাল। CompositionLocal কনফিগারেশন ডেটার জন্য সর্বোত্তম যা খুব কমই বা কখনও পরিবর্তিত হয় না।
val LocalUser = compositionLocalOf<User?> { null }
@Composable
fun AppRoot(user: User, content: @Composable () -> Unit) {
CompositionLocalProvider(LocalUser.provides(user)) {
content()
}
}
@Composable
fun UserAvatar() {
val user = LocalUser.current // স্পষ্ট প্যারামিটার ছাড়া পড়া
AsyncImage(model = user?.avatarUrl, contentDescription = "Avatar")
}
CompositionLocalProvider একটি সুযোগ তৈরি করে যার মধ্যে LocalUser.current নির্দিষ্ট মান ফেরত দেয়। UserAvatar মধ্যবর্তী ফাংশনের মাধ্যমে স্পষ্টভাবে প্যারামিটার না পাঠিয়েই ব্যবহারকারীকে পড়ে। এটি গভীর শ্রেণিবিন্যাসে বিশেষভাবে মূল্যবান যেখানে শুধুমাত্র কয়েকটি লিফ নোডে ডেটা প্রয়োজন।
সচরাচর জিজ্ঞাসা
Composition-এর সময় State পরিবর্তন একটি নতুন পুনঃসংকলন নির্ধারণ করে, যা বর্তমানটি শেষ হওয়ার পরে কার্যকর হবে। কোনও অসীম লুপ ঘটে না: Compose গ্যারান্টি দেয় যে প্রতিটি পুনঃসংকলন snapshot সিস্টেমের একটি পৃথক লেনদেনে সঞ্চালিত হয়।
আধুনিক ডিভাইসে, 50–100 Composable ফাংশন সহ একটি স্ক্রিনের Composition 1–5 ms সময় নেয়। Google 60fps ফ্রেমের জন্য 16 ms-এর মধ্যে থাকার পরামর্শ দেয়। যদি Composition এই সীমা অতিক্রম করে, LazyColumn ব্যবহার করুন বা স্ক্রিনকে ছোট ফাংশনে ভাগ করুন।
Composition-এর সরাসরি ম্যানুয়াল শুরু সম্ভব নয় — এটি Composer দ্বারা স্বয়ংক্রিয়ভাবে পরিচালিত হয়। তবে, আপনি State পরিবর্তন করে বা রুট composable-এ invalidate() কল করে পুনঃসংকলন বাধ্য করতে পারেন যদি আপনার CompositionContext-এ অ্যাক্সেস থাকে।
View শ্রেণিবিন্যাস হল Java অবজেক্টের একটি অপরিবর্তনীয় ট্রি যা একবার তৈরি হয়। Composition হল একটি ভার্চুয়াল ট্রি যা ডেটা পরিবর্তিত হলে প্রতিবার পুনর্নির্মিত হয়। View তার অবস্থা ইনস্ট্যান্স ভেরিয়েবলে সংরক্ষণ করে, Composition — ফাংশন কল অবস্থানের সাথে আবদ্ধ স্লটে।
যদি একটি Composable ফাংশন আর কল না করা হয় (যেমন, একটি if শর্ত false হয়ে যায়), Composition তার নোড সরিয়ে দেয় এবং DisposableEffect পরিষ্কার ট্রিগার করে। যখন এটি পুনরায় আবির্ভূত হয় (if আবার true হয়), একটি নতুন নোড তৈরি হয় — পুরানোটি পুনরুদ্ধার করা হয় না।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন