CompositionLocal
হল একটি টুল যা কম্পোজিশনের মাধ্যমে ডাটা ডাউন পাস করার জন্য। এই পৃষ্ঠায়, আপনি একটি CompositionLocal
কী তা আরও বিশদে শিখবেন, কীভাবে আপনার নিজস্ব CompositionLocal
তৈরি করবেন এবং আপনার ব্যবহারের ক্ষেত্রে একটি CompositionLocal
একটি ভাল সমাধান কিনা তা জানবেন।
CompositionLocal
প্রবর্তন করা হচ্ছে
সাধারণত রচনায়, প্রতিটি কম্পোজযোগ্য ফাংশনের পরামিতি হিসাবে ডেটা UI ট্রির মধ্য দিয়ে প্রবাহিত হয় । এটি একটি কম্পোজেবল এর নির্ভরতা সুস্পষ্ট করে তোলে। তবে এটি এমন ডেটার জন্য কষ্টকর হতে পারে যা খুব ঘন ঘন এবং ব্যাপকভাবে ব্যবহৃত হয় যেমন রং বা টাইপ শৈলী। নিম্নলিখিত উদাহরণ দেখুন:
@Composable fun MyApp() { // Theme information tends to be defined near the root of the application val colors = colors() } // Some composable deep in the hierarchy @Composable fun SomeTextLabel(labelText: String) { Text( text = labelText, color = colors.onPrimary // ← need to access colors here ) }
বেশিরভাগ কম্পোজেবলগুলিতে একটি স্পষ্ট প্যারামিটার নির্ভরতা হিসাবে রঙগুলি পাস করার প্রয়োজন না হওয়াকে সমর্থন করার জন্য, কম্পোজ CompositionLocal
অফার করে যা আপনাকে ট্রি-স্কোপযুক্ত নামযুক্ত বস্তু তৈরি করতে দেয় যা UI ট্রির মাধ্যমে ডেটা প্রবাহের অন্তর্নিহিত উপায় হিসাবে ব্যবহার করা যেতে পারে।
CompositionLocal
উপাদানগুলি সাধারণত UI গাছের একটি নির্দিষ্ট নোডে একটি মান সহ সরবরাহ করা হয়। কম্পোজেবল ফাংশনে CompositionLocal
কে প্যারামিটার হিসেবে ঘোষণা না করেই সেই মানটি তার কম্পোজযোগ্য বংশধরদের দ্বারা ব্যবহার করা যেতে পারে।
CompositionLocal
হল যা ম্যাটেরিয়াল থিম হুডের নিচে ব্যবহার করে। MaterialTheme
হল একটি বস্তু যা তিনটি CompositionLocal
স্থানীয় দৃষ্টান্ত প্রদান করে: colorScheme
, typography
এবং shapes
, যা আপনাকে কম্পোজিশনের যেকোনো বংশধর অংশে পরে সেগুলি পুনরুদ্ধার করতে দেয়৷ বিশেষত, এগুলি হল LocalColorScheme
, LocalShapes
, এবং LocalTypography
বৈশিষ্ট্য যা আপনি MaterialTheme
colorScheme
, shapes
এবং typography
বৈশিষ্ট্যগুলির মাধ্যমে অ্যাক্সেস করতে পারেন৷
@Composable fun MyApp() { // Provides a Theme whose values are propagated down its `content` MaterialTheme { // New values for colorScheme, typography, and shapes are available // in MaterialTheme's content lambda. // ... content here ... } } // Some composable deep in the hierarchy of MaterialTheme @Composable fun SomeTextLabel(labelText: String) { Text( text = labelText, // `primary` is obtained from MaterialTheme's // LocalColors CompositionLocal color = MaterialTheme.colorScheme.primary ) }
একটি CompositionLocal
উদাহরণ কম্পোজিশনের একটি অংশে স্কোপ করা হয় যাতে আপনি গাছের বিভিন্ন স্তরে বিভিন্ন মান প্রদান করতে পারেন। একটি CompositionLocal
এর current
মান কম্পোজিশনের সেই অংশে পূর্বপুরুষের দ্বারা প্রদত্ত নিকটতম মানের সাথে মিলে যায়।
একটি CompositionLocal
এ একটি নতুন মান প্রদান করতে, CompositionLocalProvider
ব্যবহার করুন এবং এটি ইনফিক্স ফাংশন provides
যা একটি value
সাথে একটি CompositionLocal
কী যুক্ত করে। CompositionLocalProvider
এর content
ল্যাম্বডা CompositionLocal
এর current
সম্পত্তি অ্যাক্সেস করার সময় প্রদত্ত মান পাবে। যখন একটি নতুন মান প্রদান করা হয়, তখন কম্পোজ কম্পোজিশনের অংশগুলিকে পুনরায় কম্পোজ করে যা CompositionLocal
পড়ে।
এর উদাহরণ হিসেবে, LocalContentColor
CompositionLocal
টেক্সট এবং আইকনোগ্রাফির জন্য ব্যবহৃত পছন্দের বিষয়বস্তুর রঙ রয়েছে যাতে এটি বর্তমান পটভূমির রঙের সাথে বৈপরীত্য নিশ্চিত করে। নিম্নলিখিত উদাহরণে, CompositionLocalProvider
কম্পোজিশনের বিভিন্ন অংশের জন্য বিভিন্ন মান প্রদান করতে ব্যবহৃত হয়।
@Composable fun CompositionLocalExample() { MaterialTheme { // Surface provides contentColorFor(MaterialTheme.colorScheme.surface) by default // This is to automatically make text and other content contrast to the background // correctly. Surface { Column { Text("Uses Surface's provided content color") CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.primary) { Text("Primary color provided by LocalContentColor") Text("This Text also uses primary as textColor") CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.error) { DescendantExample() } } } } } } @Composable fun DescendantExample() { // CompositionLocalProviders also work across composable functions Text("This Text uses the error color now") }
চিত্র 1. CompositionLocalExample
প্রিভিউ LocalExample composable.
শেষ উদাহরণে, CompositionLocal
দৃষ্টান্তগুলি অভ্যন্তরীণভাবে উপাদান কম্পোজেবল দ্বারা ব্যবহৃত হয়েছিল। একটি CompositionLocal
এর বর্তমান মান অ্যাক্সেস করতে, এর current
সম্পত্তি ব্যবহার করুন। নিম্নলিখিত উদাহরণে, LocalContext
CompositionLocal
এর বর্তমান Context
মান যা সাধারণত Android অ্যাপগুলিতে ব্যবহৃত হয় পাঠ্য বিন্যাস করতে ব্যবহৃত হয়:
@Composable fun FruitText(fruitSize: Int) { // Get `resources` from the current value of LocalContext val resources = LocalContext.current.resources val fruitText = remember(resources, fruitSize) { resources.getQuantityString(R.plurals.fruit_title, fruitSize) } Text(text = fruitText) }
আপনার নিজস্ব CompositionLocal
তৈরি করা
CompositionLocal
হল একটি টুল যা কম্পোজিশনের মাধ্যমে ডাটা ডাউন পাস করার জন্য ।
CompositionLocal
ব্যবহার করার জন্য আরেকটি মূল সংকেত হল যখন প্যারামিটারটি ক্রস-কাটিং করা হয় এবং বাস্তবায়নের মধ্যবর্তী স্তরগুলি এটির অস্তিত্ব সম্পর্কে সচেতন হওয়া উচিত নয় , কারণ এই মধ্যবর্তী স্তরগুলিকে সচেতন করা কম্পোজেবলের উপযোগিতাকে সীমিত করবে। উদাহরণস্বরূপ, অ্যান্ড্রয়েড অনুমতিগুলির জন্য অনুসন্ধানের জন্য হুডের নীচে একটি CompositionLocal
দ্বারা সরবরাহ করা হয়৷ একটি মিডিয়া পিকার কম্পোজেবল তার API পরিবর্তন না করে ডিভাইসে অনুমতি-সুরক্ষিত সামগ্রী অ্যাক্সেস করার জন্য নতুন কার্যকারিতা যোগ করতে পারে এবং মিডিয়া পিকারের কলকারীদের পরিবেশ থেকে ব্যবহৃত এই অতিরিক্ত প্রসঙ্গ সম্পর্কে সচেতন হতে হবে।
যাইহোক, CompositionLocal
সর্বদা সর্বোত্তম সমাধান নয়। আমরা CompositionLocal
অতিরিক্ত ব্যবহারকে নিরুৎসাহিত করি কারণ এটি কিছু খারাপ দিক নিয়ে আসে:
CompositionLocal
একটি কম্পোজেবল এর আচরণ সম্পর্কে যুক্তি করা কঠিন করে তোলে । যেহেতু তারা অন্তর্নিহিত নির্ভরতা তৈরি করে, কম্পোজেবলের কলকারীরা যেগুলি তাদের ব্যবহার করে তাদের নিশ্চিত করতে হবে যে প্রতিটি CompositionLocal
জন্য একটি মান সন্তুষ্ট।
তদ্ব্যতীত, এই নির্ভরতার জন্য সত্যের কোনও সুস্পষ্ট উত্স নাও থাকতে পারে কারণ এটি রচনার যে কোনও অংশে রূপান্তরিত হতে পারে। সুতরাং, যখন কোনও সমস্যা দেখা দেয় তখন অ্যাপটিকে ডিবাগ করা আরও চ্যালেঞ্জিং হতে পারে কারণ current
মানটি কোথায় দেওয়া হয়েছে তা দেখতে আপনাকে কম্পোজিশনটি নেভিগেট করতে হবে। আইডিই-তে ব্যবহার খুঁজুন বা কম্পোজ লেআউট ইন্সপেক্টরের মতো টুলগুলি এই সমস্যাটি কমানোর জন্য যথেষ্ট তথ্য প্রদান করে।
CompositionLocal
ব্যবহার করবেন কিনা তা স্থির করা
কিছু শর্ত রয়েছে যা CompositionLocal
আপনার ব্যবহারের ক্ষেত্রে একটি ভাল সমাধান করতে পারে:
একটি CompositionLocal
একটি ভাল ডিফল্ট মান থাকা উচিত । যদি কোনও ডিফল্ট মান না থাকে, তাহলে আপনাকে অবশ্যই গ্যারান্টি দিতে হবে যে একজন ডেভেলপারের পক্ষে এমন পরিস্থিতিতে যাওয়া অত্যন্ত কঠিন যেখানে CompositionLocal
জন্য একটি মান প্রদান করা হয় না। একটি ডিফল্ট মান প্রদান না করা সমস্যা এবং হতাশার কারণ হতে পারে পরীক্ষা তৈরি করার সময় বা একটি কম্পোজেবল প্রিভিউ করার সময় যেটি CompositionLocal
ব্যবহার করে তা স্পষ্টভাবে প্রদান করতে হবে।
ট্রি-স্কোপড বা সাব-হায়ারার্কি স্কোপড বলে মনে করা হয় না এমন ধারণাগুলির জন্য CompositionLocal
এড়িয়ে চলুন । একটি CompositionLocal
অর্থবোধক হয় যখন এটি সম্ভাব্যভাবে যেকোনো বংশধর দ্বারা ব্যবহার করা যেতে পারে, তাদের মধ্যে কয়েকটি দ্বারা নয়।
যদি আপনার ব্যবহারের ক্ষেত্রে এই প্রয়োজনীয়তাগুলি পূরণ না করে, একটি CompositionLocal
তৈরি করার আগে বিবেচনা করার জন্য বিকল্প বিভাগটি দেখুন।
একটি খারাপ অনুশীলনের একটি উদাহরণ হল একটি CompositionLocal
তৈরি করা যা একটি নির্দিষ্ট স্ক্রিনের ViewModel
ধারণ করে যাতে সেই স্ক্রিনের সমস্ত কম্পোজেবল কিছু যুক্তি সম্পাদন করার জন্য ViewModel
একটি রেফারেন্স পেতে পারে। এটি একটি খারাপ অভ্যাস কারণ একটি নির্দিষ্ট UI ট্রির নীচে সমস্ত কম্পোজেবলের একটি ViewModel
সম্পর্কে জানার প্রয়োজন নেই৷ ভাল অভ্যাস হল কম্পোজেবলের কাছে শুধুমাত্র সেই তথ্যগুলি প্রেরণ করা যা তাদের প্রয়োজনীয় প্যাটার্ন অনুসরণ করে যে অবস্থাটি নিচে প্রবাহিত হয় এবং ঘটনাগুলি উপরে উঠে যায় । এই পদ্ধতিটি আপনার কম্পোজেবলগুলিকে আরও পুনঃব্যবহারযোগ্য এবং পরীক্ষা করা সহজ করে তুলবে।
একটি CompositionLocal
তৈরি করা
একটি CompositionLocal
তৈরি করার জন্য দুটি API আছে:
compositionLocalOf
: পুনর্গঠনের সময় প্রদত্ত মান পরিবর্তন করা শুধুমাত্র সেই বিষয়বস্তুটিকে বাতিল করে যা এরcurrent
মান পড়ে।staticCompositionLocalOf
:compositionLocalOf
বিপরীতে, একটিstaticCompositionLocalOf
এর রিডগুলি রচনা দ্বারা ট্র্যাক করা হয় না। মান পরিবর্তন করা হলে সমগ্রcontent
ল্যাম্বডা যেখানেCompositionLocal
পুনরায় কম্পোজ করার জন্য প্রদান করা হয়, শুধুমাত্র সেই জায়গাগুলির পরিবর্তে যেখানেcurrent
মানটি রচনায় পড়া হয়।
CompositionLocal
এ প্রদত্ত মান যদি পরিবর্তন হওয়ার সম্ভাবনা খুব কম হয় বা কখনই পরিবর্তন হবে না, কর্মক্ষমতা সুবিধা পেতে staticCompositionLocalOf
ব্যবহার করুন।
উদাহরণস্বরূপ, UI উপাদানের জন্য একটি ছায়া ব্যবহার করে কম্পোজেবলগুলিকে যেভাবে উন্নত করা হয় সেভাবে একটি অ্যাপের ডিজাইন সিস্টেম মতামত দেওয়া যেতে পারে। যেহেতু অ্যাপের বিভিন্ন উচ্চতা সমগ্র UI ট্রি জুড়ে প্রচারিত হওয়া উচিত, তাই আমরা একটি CompositionLocal
ব্যবহার করি। যেহেতু CompositionLocal
মান শর্তসাপেক্ষে সিস্টেম থিমের উপর ভিত্তি করে প্রাপ্ত হয়, আমরা compositionLocalOf
API ব্যবহার করি:
// LocalElevations.kt file data class Elevations(val card: Dp = 0.dp, val default: Dp = 0.dp) // Define a CompositionLocal global object with a default // This instance can be accessed by all composables in the app val LocalElevations = compositionLocalOf { Elevations() }
একটি CompositionLocal
মান প্রদান
CompositionLocalProvider
composable মানগুলিকে CompositionLocal
দৃষ্টান্তের সাথে প্রদত্ত অনুক্রমের জন্য আবদ্ধ করে । একটি CompositionLocal
এ একটি নতুন মান প্রদান করতে, provides
ইনফিক্স ফাংশন ব্যবহার করুন যা নিম্নরূপ একটি value
সাথে একটি CompositionLocal
কী যুক্ত করে:
// MyActivity.kt file class MyActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // Calculate elevations based on the system theme val elevations = if (isSystemInDarkTheme()) { Elevations(card = 1.dp, default = 1.dp) } else { Elevations(card = 0.dp, default = 0.dp) } // Bind elevation as the value for LocalElevations CompositionLocalProvider(LocalElevations provides elevations) { // ... Content goes here ... // This part of Composition will see the `elevations` instance // when accessing LocalElevations.current } } } }
CompositionLocal
গ্রাস করা
CompositionLocal.current
নিকটতম CompositionLocalProvider
দ্বারা প্রদত্ত মান প্রদান করে যা সেই CompositionLocal
কে একটি মান প্রদান করে:
@Composable fun SomeComposable() { // Access the globally defined LocalElevations variable to get the // current Elevations in this part of the Composition MyCard(elevation = LocalElevations.current.card) { // Content } }
বিবেচনা করার বিকল্প
একটি CompositionLocal
কিছু ব্যবহারের ক্ষেত্রে একটি অত্যধিক সমাধান হতে পারে। যদি আপনার ব্যবহারের ক্ষেত্রে CompositionLocal বিভাগ ব্যবহার করার সিদ্ধান্ত নেওয়ার মধ্যে নির্দিষ্ট মানদণ্ড পূরণ না করে, তাহলে অন্য সমাধান সম্ভবত আপনার ব্যবহারের ক্ষেত্রে আরও উপযুক্ত হতে পারে।
সুস্পষ্ট পরামিতি পাস
কম্পোজেবলের নির্ভরতা সম্পর্কে স্পষ্ট হওয়া একটি ভাল অভ্যাস। আমরা সুপারিশ করি যে আপনি কম্পোজেবল পাস করুন শুধুমাত্র তাদের যা প্রয়োজন । কম্পোজেবলের ডিকপলিং এবং পুনঃব্যবহারকে উত্সাহিত করার জন্য, প্রতিটি কম্পোজেবলের সম্ভাব্য সর্বনিম্ন পরিমাণ তথ্য রাখা উচিত।
@Composable fun MyComposable(myViewModel: MyViewModel = viewModel()) { // ... MyDescendant(myViewModel.data) } // Don't pass the whole object! Just what the descendant needs. // Also, don't pass the ViewModel as an implicit dependency using // a CompositionLocal. @Composable fun MyDescendant(myViewModel: MyViewModel) { /* ... */ } // Pass only what the descendant needs @Composable fun MyDescendant(data: DataToDisplay) { // Display data }
নিয়ন্ত্রণের বিপরীত
একটি কম্পোজেবলে অপ্রয়োজনীয় নির্ভরতা পাস করা এড়ানোর আরেকটি উপায় হল নিয়ন্ত্রণের বিপরীতের মাধ্যমে। বংশধর কিছু যুক্তি কার্যকর করার জন্য নির্ভরতা গ্রহণ করার পরিবর্তে, পিতামাতা এটি করেন।
নিম্নলিখিত উদাহরণটি দেখুন যেখানে একজন বংশধরকে কিছু ডেটা লোড করার অনুরোধটি ট্রিগার করতে হবে:
@Composable fun MyComposable(myViewModel: MyViewModel = viewModel()) { // ... MyDescendant(myViewModel) } @Composable fun MyDescendant(myViewModel: MyViewModel) { Button(onClick = { myViewModel.loadData() }) { Text("Load data") } }
মামলার উপর নির্ভর করে, MyDescendant
অনেক দায়িত্ব থাকতে পারে। এছাড়াও, MyViewModel
নির্ভরতা হিসাবে পাস করা MyDescendant
কম পুনঃব্যবহারযোগ্য করে তোলে কারণ তারা এখন একত্রিত হয়েছে। বিকল্পটি বিবেচনা করুন যা বংশধরের মধ্যে নির্ভরতা পাস করে না এবং নিয়ন্ত্রণ নীতিগুলির বিপরীত ব্যবহার করে যা পূর্বপুরুষকে যুক্তি সম্পাদনের জন্য দায়ী করে:
@Composable fun MyComposable(myViewModel: MyViewModel = viewModel()) { // ... ReusableLoadDataButton( onLoadClick = { myViewModel.loadData() } ) } @Composable fun ReusableLoadDataButton(onLoadClick: () -> Unit) { Button(onClick = onLoadClick) { Text("Load data") } }
এই পদ্ধতিটি কিছু ব্যবহারের ক্ষেত্রে আরও উপযুক্ত হতে পারে কারণ এটি শিশুকে তার নিকটবর্তী পূর্বপুরুষদের থেকে আলাদা করে দেয় । পূর্বপুরুষ কম্পোজেবলগুলি আরও নমনীয় নিম্ন-স্তরের কম্পোজেবল থাকার পক্ষে আরও জটিল হয়ে ওঠে।
একইভাবে, @Composable
কন্টেন্ট ল্যাম্বডাস একই সুবিধা পেতে একই ভাবে ব্যবহার করা যেতে পারে :
@Composable fun MyComposable(myViewModel: MyViewModel = viewModel()) { // ... ReusablePartOfTheScreen( content = { Button( onClick = { myViewModel.loadData() } ) { Text("Confirm") } } ) } @Composable fun ReusablePartOfTheScreen(content: @Composable () -> Unit) { Column { // ... content() } }
আপনার জন্য প্রস্তাবিত
- দ্রষ্টব্য: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট প্রদর্শিত হয়
- রচনায় একটি থিমের অ্যানাটমি
- কম্পোজে ভিউ ব্যবহার করা
- জেটপ্যাক রচনার জন্য কোটলিন