CompositionLocal সহ স্থানীয়ভাবে স্কোপড ডেটা

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 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()
    }
}

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %} ,

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 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()
    }
}

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %} ,

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 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()
    }
}

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %} ,

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 কমপোজেবলের পূর্বরূপ।

শেষ উদাহরণে, CompositionLocal উদাহরণগুলি অভ্যন্তরীণভাবে উপাদানগুলির কম্পোজেবল দ্বারা ব্যবহৃত হয়েছিল। একটি CompositionLocal বর্তমান মান অ্যাক্সেস করতে, এর current সম্পত্তিটি ব্যবহার করুন। নিম্নলিখিত উদাহরণে, অ্যান্ড্রয়েড অ্যাপ্লিকেশনগুলিতে সাধারণত ব্যবহৃত হয় এমন LocalContext CompositionLocal বর্তমান Context মানটি পাঠ্যটি ফর্ম্যাট করতে ব্যবহৃত হয়:

@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 দ্বারা সরবরাহ করা হয়। একটি মিডিয়া পিকার কমপোজেবল ডিভাইসে এর এপিআই পরিবর্তন না করে এবং মিডিয়া পিকের কলারদের পরিবেশ থেকে ব্যবহৃত এই যুক্ত প্রসঙ্গ সম্পর্কে সচেতন হওয়ার প্রয়োজনে ডিভাইসে অনুমতি-সুরক্ষিত সামগ্রী অ্যাক্সেস করতে নতুন কার্যকারিতা যুক্ত করতে পারে।

তবে, CompositionLocal সর্বদা সেরা সমাধান নয়। আমরা কিছু ডাউনসাইডের সাথে আসার সাথে সাথে আমরা ওভার ব্যবহারকে CompositionLocal করি:

CompositionLocal একটি কমপোজেবলের আচরণ সম্পর্কে যুক্তিযুক্ত আরও শক্ত করে তোলে । যেহেতু তারা অন্তর্নিহিত নির্ভরতা তৈরি করে, কমপোজেবলগুলির কলকারী যা তাদের ব্যবহার করে তা নিশ্চিত করা দরকার যে প্রতিটি CompositionLocal জন্য একটি মান সন্তুষ্ট।

তদুপরি, এই নির্ভরতার জন্য সত্যের কোনও সুস্পষ্ট উত্স থাকতে পারে না কারণ এটি রচনার কোনও অংশে পরিবর্তিত হতে পারে। সুতরাং, সমস্যা দেখা দিলে অ্যাপটি ডিবাগিং করা আরও চ্যালেঞ্জিং হতে পারে কারণ current মানটি কোথায় সরবরাহ করা হয়েছিল তা দেখার জন্য আপনাকে রচনাটি নেভিগেট করতে হবে। আইডিই বা রচনা লেআউট ইন্সপেক্টরগুলিতে ব্যবহারের সন্ধান করার মতো সরঞ্জামগুলি এই সমস্যাটি প্রশমিত করার জন্য পর্যাপ্ত তথ্য সরবরাহ করে।

CompositionLocal ব্যবহার করবেন কিনা তা সিদ্ধান্ত নিচ্ছেন

কিছু শর্ত রয়েছে যা আপনার ব্যবহারের ক্ষেত্রে CompositionLocal একটি ভাল সমাধান করতে পারে:

একটি CompositionLocal একটি ভাল ডিফল্ট মান থাকতে হবে । যদি কোনও ডিফল্ট মান না থাকে তবে আপনাকে অবশ্যই গ্যারান্টি দিতে হবে যে কোনও বিকাশকারীর পক্ষে এমন পরিস্থিতিতে প্রবেশ করা অত্যন্ত কঠিন যেখানে CompositionLocal জন্য একটি মান সরবরাহ করা হয়নি। একটি ডিফল্ট মান সরবরাহ না করা পরীক্ষাগুলি তৈরি করার সময় বা কোনও কম্পোজেবলের পূর্বরূপ দেখার সময় সমস্যা এবং হতাশার কারণ হতে পারে যা এই CompositionLocal ব্যবহার করে এটি সর্বদা সুস্পষ্টভাবে সরবরাহ করা প্রয়োজন।

যে ধারণাগুলি গাছ-স্কোপড বা সাব-হায়ারার্কি স্কোপড হিসাবে ভাবা হয় না তার জন্য CompositionLocal এড়িয়ে চলুন। একটি CompositionLocal যখন এটি কোনও বংশধর দ্বারা সম্ভাব্যভাবে ব্যবহার করা যেতে পারে, তখন তাদের কয়েকজনের দ্বারা নয়।

যদি আপনার ব্যবহারের ক্ষেত্রে এই প্রয়োজনীয়তাগুলি পূরণ না করে, একটি CompositionLocal তৈরির আগে বিভাগটি বিবেচনা করার বিকল্পগুলি দেখুন।

একটি খারাপ অনুশীলনের একটি উদাহরণ একটি CompositionLocal তৈরি করা যা একটি নির্দিষ্ট স্ক্রিনের ViewModel ধারণ করে যাতে সেই স্ক্রিনের সমস্ত কম্পোজেবলগুলি কিছু যুক্তি সম্পাদন করার জন্য ViewModel একটি রেফারেন্স পেতে পারে। এটি একটি খারাপ অনুশীলন কারণ কোনও নির্দিষ্ট ইউআই গাছের নীচে সমস্ত কম্পোজেবলকে ViewModel সম্পর্কে জানতে হবে না। ভাল অনুশীলনটি হ'ল কমপোজেবলগুলিতে কেবল তাদের যে তথ্যটি প্রবাহিত হয় এবং ইভেন্টগুলি প্রবাহিত হয় তার অনুসরণ করে তাদের প্রয়োজনীয় তথ্যগুলি পাস করা। এই পদ্ধতির আপনার কম্পোজেবলগুলি আরও পুনরায় ব্যবহারযোগ্য এবং পরীক্ষা করা সহজ করে তুলবে।

একটি CompositionLocal তৈরি করা

একটি CompositionLocal তৈরির জন্য দুটি এপিআই রয়েছে:

  • compositionLocalOf : পুনরুদ্ধার চলাকালীন প্রদত্ত মান পরিবর্তন করা কেবল তার current মানটি পড়ার বিষয়বস্তুকে অবৈধ করে তোলে।

  • staticCompositionLocalOf : compositionLocalOf বিপরীতে, staticCompositionLocalOf পাঠগুলি রচনা দ্বারা ট্র্যাক করা হয় না। মান পরিবর্তন করার ফলে content ল্যাম্বডা সম্পূর্ণরূপে যেখানে CompositionLocal পুনরায় সংযুক্ত করার জন্য সরবরাহ করা হয়, কেবল সেই জায়গাগুলির পরিবর্তে যেখানে current মানটি রচনাটিতে পড়া হয়।

যদি CompositionLocal সরবরাহ করা মানটি পরিবর্তিত হওয়ার সম্ভাবনা খুব কম বা কখনই পরিবর্তন না হয় তবে পারফরম্যান্স সুবিধাগুলি পেতে staticCompositionLocalOf ব্যবহার করুন।

উদাহরণস্বরূপ, কোনও অ্যাপের ডিজাইন সিস্টেমটি ইউআই উপাদানটির জন্য ছায়া ব্যবহার করে কমপোজেবলগুলি যেভাবে উন্নত করা হয়েছে তাতে মতামত দেওয়া যেতে পারে। যেহেতু অ্যাপ্লিকেশনটির জন্য বিভিন্ন উচ্চতাগুলি ইউআই ট্রি জুড়ে প্রচার করা উচিত, তাই আমরা একটি CompositionLocal ব্যবহার করি। যেহেতু CompositionLocal মানটি শর্তসাপেক্ষে সিস্টেম থিমের উপর ভিত্তি করে উত্পন্ন হয়, আমরা compositionLocalOf এপিআই ব্যবহার করি:

// 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 কমপোজেবল প্রদত্ত শ্রেণিবিন্যাসের জন্য 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 কিছু ব্যবহারের ক্ষেত্রে অতিরিক্ত সমাধান হতে পারে। যদি আপনার ব্যবহারের কেসটি কম্পোজিশনলোকাল বিভাগটি ব্যবহার করবেন কিনা তা সিদ্ধান্তে উল্লিখিত মানদণ্ডগুলি পূরণ না করে, তবে আপনার ব্যবহারের ক্ষেত্রে আরও একটি সমাধান সম্ভবত আরও উপযুক্ত হতে পারে।

সুস্পষ্ট পরামিতি পাস

কমপোজেবলের নির্ভরতা সম্পর্কে সুস্পষ্ট হওয়া একটি ভাল অভ্যাস। আমরা আপনাকে সুপারিশ করি যে আপনি তাদের প্রয়োজনগুলি কেবল কমপোজেবলগুলি পাস করুন । কমপোজেবলগুলির ডিকোপলিং এবং পুনরায় ব্যবহারকে উত্সাহিত করার জন্য, প্রতিটি কমপোজেবলের কমপক্ষে তথ্যটি সম্ভব হওয়া উচিত।

@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()
    }
}

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %}