স্টেট হোল্ডার এবং UI স্টেট (original) (raw)

UI লেয়ার গাইড ইউআই লেয়ারের জন্য UI স্টেট তৈরি ও পরিচালনার একটি উপায় হিসাবে ইউনিডাইরেকশনাল ডেটা ফ্লো (UDF) নিয়ে আলোচনা করে।

ডেটা ডাটা স্তর থেকে UI এ একমুখীভাবে প্রবাহিত হয়।

চিত্র 1. একমুখী তথ্য প্রবাহ।

এটি রাষ্ট্র ধারক নামে একটি বিশেষ শ্রেণীর কাছে UDF ব্যবস্থাপনা অর্পণ করার সুবিধাগুলিও তুলে ধরে। আপনি একটি ViewModel বা একটি প্লেইন ক্লাসের মাধ্যমে একটি স্টেট হোল্ডার বাস্তবায়ন করতে পারেন। এই ডকুমেন্টটি স্টেট হোল্ডারদের এবং UI লেয়ারে তারা যে ভূমিকা পালন করে তার উপর ঘনিষ্ঠভাবে নজর দেয়।

এই ডকুমেন্টের শেষে, ইউআই লেয়ারে অ্যাপ্লিকেশানের অবস্থা কীভাবে পরিচালনা করতে হয় সে সম্পর্কে আপনার ধারণা থাকা উচিত; এটি UI রাজ্য উত্পাদন পাইপলাইন। আপনি নিম্নলিখিত বুঝতে এবং জানতে সক্ষম হওয়া উচিত:

UI স্টেট প্রোডাকশন পাইপলাইনের উপাদান

UI অবস্থা এবং যুক্তি যা এটি তৈরি করে তা UI স্তরকে সংজ্ঞায়িত করে।

UI অবস্থা

UI স্টেট হল সেই সম্পত্তি যা UI বর্ণনা করে। দুই ধরনের UI অবস্থা আছে:

যুক্তিবিদ্যা

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

যুক্তি UI অবস্থা তৈরি করে

চিত্র 2. UI রাজ্যের প্রযোজক হিসাবে যুক্তি।

একটি অ্যাপ্লিকেশনে যুক্তি ব্যবসায়িক যুক্তি বা UI যুক্তি হতে পারে:

অ্যান্ড্রয়েড লাইফসাইকেল এবং ইউআই স্টেট এবং লজিকের ধরন

UI স্তরের দুটি অংশ রয়েছে: একটি নির্ভরশীল এবং অন্যটি UI জীবনচক্র থেকে স্বাধীন। এই বিচ্ছেদ প্রতিটি অংশের জন্য উপলব্ধ ডেটা উত্স নির্ধারণ করে, এবং সেইজন্য বিভিন্ন ধরনের UI অবস্থা এবং যুক্তি প্রয়োজন।

উপরের সারণীগুলির সাথে সংক্ষিপ্ত করা যেতে পারে:

UI জীবনচক্র স্বাধীন UI জীবনচক্র নির্ভরশীল
ব্যবসায়িক যুক্তি UI লজিক
স্ক্রীন UI অবস্থা

UI রাজ্য উত্পাদন পাইপলাইন

UI স্টেট প্রোডাকশন পাইপলাইন UI স্টেট তৈরির জন্য গৃহীত পদক্ষেপগুলিকে বোঝায়। এই পদক্ষেপগুলি আগে সংজ্ঞায়িত যুক্তির ধরনগুলির প্রয়োগকে অন্তর্ভুক্ত করে এবং সম্পূর্ণরূপে আপনার UI এর চাহিদার উপর নির্ভরশীল৷ কিছু UI পাইপলাইনের UI লাইফসাইকেল স্বাধীন এবং UI লাইফসাইকেল নির্ভরশীল উভয় অংশ থেকে উপকৃত হতে পারে, হয় না হয়

অর্থাৎ, UI স্তর পাইপলাইনের নিম্নোক্ত স্থানান্তরগুলি বৈধ:

@Composable  
fun Counter() {  
    // The UI state is managed by the UI itself  
    var count by remember { mutableStateOf(0) }  
    Row {  
        Button(onClick = { ++count }) {  
            Text(text = "Increment")  
        }  
        Button(onClick = { --count }) {  
            Text(text = "Decrement")  
        }  
    }  
}  
@Composable  
fun ContactsList(contacts: List<Contact>) {  
    val listState = rememberLazyListState()  
    val isAtTopOfList by remember {  
        derivedStateOf {  
            listState.firstVisibleItemIndex < 3  
        }  
    }  
    // Create the LazyColumn with the lazyListState  
    ...  
    // Show or hide the button (UI logic) based on the list scroll position  
    AnimatedVisibility(visible = !isAtTopOfList) {  
        ScrollToTopButton()  
    }  
}  
@Composable  
fun UserProfileScreen(viewModel: UserProfileViewModel = hiltViewModel()) {  
    // Read screen UI state from the business logic state holder  
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()  
    // Call on the UserAvatar Composable to display the photo  
    UserAvatar(picture = uiState.profilePicture)  
}  
@Composable  
fun ContactsList(viewModel: ContactsViewModel = hiltViewModel()) {  
    // Read screen UI state from the business logic state holder  
    val uiState by viewModel.uiState.collectAsStateWithLifecycle()  
    val contacts = uiState.contacts  
    val deepLinkedContact = uiState.deepLinkedContact  
    val listState = rememberLazyListState()  
    // Create the LazyColumn with the lazyListState  
    ...  
    // Perform UI logic that depends on information from business logic  
    if (deepLinkedContact != null && contacts.isNotEmpty()) {  
        LaunchedEffect(listState, deepLinkedContact, contacts) {  
            val deepLinkedContactIndex = contacts.indexOf(deepLinkedContact)  
            if (deepLinkedContactIndex >= 0) {  
              // Scroll to deep linked item  
              listState.animateScrollToItem(deepLinkedContactIndex)  
            }  
        }  
    }  
}  

যে ক্ষেত্রে উভয় ধরনের যুক্তিই UI স্টেট প্রোডাকশন পাইপলাইনে প্রয়োগ করা হয়, ব্যবসায়িক যুক্তি সর্বদা UI লজিকের আগে প্রয়োগ করা আবশ্যক । UI লজিকের পরে ব্যবসায়িক যুক্তি প্রয়োগ করার চেষ্টা করা বোঝায় যে ব্যবসায়িক যুক্তি UI যুক্তির উপর নির্ভর করে। নিম্নলিখিত বিভাগগুলি বিভিন্ন যুক্তির ধরন এবং তাদের রাষ্ট্র ধারকদের গভীরভাবে দেখার মাধ্যমে কেন এটি একটি সমস্যা তা কভার করে।

ডেটা উত্পাদনকারী স্তর থেকে UI এ ডেটা প্রবাহিত হয়

চিত্র 3. UI স্তরে যুক্তির প্রয়োগ।

রাষ্ট্র ধারক এবং তাদের দায়িত্ব

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

এটি নিম্নলিখিত সুবিধাগুলি তৈরি করে:

এর আকার বা সুযোগ নির্বিশেষে, প্রতিটি UI উপাদানের সংশ্লিষ্ট স্টেট হোল্ডারের সাথে 1:1 সম্পর্ক রয়েছে। তদ্ব্যতীত, একজন রাষ্ট্র ধারক অবশ্যই ব্যবহারকারীর ক্রিয়াকলাপ গ্রহণ এবং প্রক্রিয়া করতে সক্ষম হবেন যার ফলে একটি UI অবস্থার পরিবর্তন হতে পারে এবং পরবর্তী রাষ্ট্র পরিবর্তন অবশ্যই করতে হবে।

রাষ্ট্র ধারকদের প্রকার

ইউআই স্টেট এবং লজিকের মতোই, ইউআই লেয়ারে দুই ধরনের স্টেট হোল্ডার রয়েছে যা UI জীবনচক্রের সাথে তাদের সম্পর্ক দ্বারা সংজ্ঞায়িত করা হয়েছে:

নিম্নলিখিত বিভাগগুলি ব্যবসায়িক লজিক স্টেট হোল্ডার থেকে শুরু করে রাষ্ট্র ধারকদের ধরনগুলি ঘনিষ্ঠভাবে দেখে।

ব্যবসায়িক যুক্তি এবং এর রাষ্ট্র ধারক

বিজনেস লজিক স্টেট হোল্ডাররা ব্যবহারকারীর ইভেন্টগুলি প্রক্রিয়া করে এবং ডেটা বা ডোমেন স্তরগুলি থেকে স্ক্রীন UI স্টেটে ডেটা রূপান্তর করে। অ্যান্ড্রয়েড লাইফসাইকেল এবং অ্যাপ কনফিগারেশন পরিবর্তনগুলি বিবেচনা করার সময় একটি সর্বোত্তম ব্যবহারকারীর অভিজ্ঞতা প্রদান করার জন্য, ব্যবসায়িক যুক্তি ব্যবহার করে এমন রাষ্ট্র ধারকদের নিম্নলিখিত বৈশিষ্ট্যগুলি থাকা উচিত:

সম্পত্তি বিস্তারিত
UI স্টেট তৈরি করে বিজনেস লজিক স্টেট হোল্ডাররা তাদের UI এর জন্য UI স্টেট তৈরি করার জন্য দায়ী। এই UI অবস্থা প্রায়শই ব্যবহারকারীর ইভেন্ট প্রক্রিয়াকরণ এবং ডোমেন এবং ডেটা স্তর থেকে ডেটা পড়ার ফলাফল।
কার্যকলাপ বিনোদন মাধ্যমে বজায় রাখা বিজনেস লজিক স্টেট হোল্ডাররা তাদের স্টেট এবং স্টেট প্রসেসিং পাইপলাইনগুলিকে Activity রিক্রিয়েশন জুড়ে ধরে রাখে, একটি নিরবিচ্ছিন্ন ব্যবহারকারীর অভিজ্ঞতা প্রদানে সহায়তা করে। যে ক্ষেত্রে রাজ্য ধারককে ধরে রাখা যায় না এবং পুনরায় তৈরি করা হয় (সাধারণত প্রক্রিয়া মৃত্যুর পরে), রাজ্য ধারককে একটি সামঞ্জস্যপূর্ণ ব্যবহারকারীর অভিজ্ঞতা নিশ্চিত করতে সহজেই তার শেষ অবস্থা পুনরায় তৈরি করতে সক্ষম হতে হবে।
দীর্ঘজীবী রাষ্ট্রের অধিকারী বিজনেস লজিক স্টেট হোল্ডাররা প্রায়ই নেভিগেশন গন্তব্যের জন্য স্টেট পরিচালনা করতে ব্যবহৃত হয়। ফলস্বরূপ, নেভিগেশন গ্রাফ থেকে সরানো না হওয়া পর্যন্ত তারা প্রায়শই নেভিগেশন পরিবর্তন জুড়ে তাদের অবস্থা সংরক্ষণ করে।
এটির UI এর জন্য অনন্য এবং এটি পুনরায় ব্যবহারযোগ্য নয় বিজনেস লজিক স্টেট হোল্ডাররা সাধারণত একটি নির্দিষ্ট অ্যাপ ফাংশনের জন্য স্টেট তৈরি করে, উদাহরণস্বরূপ একটি TaskEditViewModel বা একটি TaskListViewModel , এবং সেইজন্য শুধুমাত্র সেই অ্যাপ ফাংশনের জন্য প্রযোজ্য। একই রাজ্য ধারক বিভিন্ন ফর্ম ফ্যাক্টর জুড়ে এই অ্যাপ্লিকেশন ফাংশন সমর্থন করতে পারেন. উদাহরণস্বরূপ, অ্যাপের মোবাইল, টিভি এবং ট্যাবলেট সংস্করণ একই ব্যবসায়িক লজিক স্টেট হোল্ডার পুনরায় ব্যবহার করতে পারে।

উদাহরণ স্বরূপ "Now in Android " অ্যাপে লেখক নেভিগেশন গন্তব্য বিবেচনা করুন:

নাও ইন অ্যান্ড্রয়েড অ্যাপ দেখায় যে কীভাবে একটি প্রধান অ্যাপ ফাংশন প্রতিনিধিত্বকারী একটি নেভিগেশন গন্তব্য থাকা উচিত তার নিজস্ব অনন্য ব্যবসা যুক্তি রাষ্ট্র ধারক.

চিত্র 4. The Now in Android অ্যাপ।

বিজনেস লজিক স্টেট হোল্ডার হিসেবে কাজ করে, AuthorViewModel এই ক্ষেত্রে UI স্টেট তৈরি করে:

@HiltViewModel
class AuthorViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val authorsRepository: AuthorsRepository,
    newsRepository: NewsRepository
) : ViewModel() {

    val uiState: StateFlow<AuthorScreenUiState> = …

    // Business logic
    fun followAuthor(followed: Boolean) {
      …
    }
}

লক্ষ্য করুন যে AuthorViewModel এর বৈশিষ্ট্যগুলি পূর্বে বর্ণিত হয়েছে:

সম্পত্তি বিস্তারিত
AuthorScreenUiState তৈরি করে AuthorViewModel AuthorsRepository এবং NewsRepository থেকে ডেটা পড়ে এবং AuthorScreenUiState তৈরি করতে সেই ডেটা ব্যবহার করে। এটি ব্যবসায়িক যুক্তিও প্রয়োগ করে যখন ব্যবহারকারী AuthorsRepository এ অর্পণ করে একজন Author অনুসরণ করতে বা আনফলো করতে চায়।
ডেটা স্তরে অ্যাক্সেস আছে AuthorsRepository এবং NewsRepository এর একটি উদাহরণ এটির কনস্ট্রাক্টরে এটিকে পাস করা হয়, এটি একটি Author অনুসরণ করার ব্যবসায়িক যুক্তি বাস্তবায়নের অনুমতি দেয়।
Activity বিনোদন বেঁচে যেহেতু এটি একটি ViewModel এর সাথে প্রয়োগ করা হয়েছে, এটি দ্রুত Activity বিনোদন জুড়ে ধরে রাখা হবে। প্রক্রিয়া মৃত্যুর ক্ষেত্রে, ডেটা স্তর থেকে UI অবস্থা পুনরুদ্ধার করার জন্য প্রয়োজনীয় ন্যূনতম পরিমাণ তথ্য সরবরাহ করতে SavedStateHandle অবজেক্ট থেকে পড়া যেতে পারে।
দীর্ঘজীবী রাষ্ট্রের অধিকারী ViewModel নেভিগেশন গ্রাফে স্কোপ করা হয়েছে, তাই লেখক গন্তব্যটি নেভিগেশন গ্রাফ থেকে সরানো না হলে, uiState StateFlow এর UI অবস্থা মেমরিতে থাকবে। StateFlow -এর ব্যবহার ব্যবসায়িক যুক্তির প্রয়োগ করার সুবিধাও যোগ করে যা রাষ্ট্রকে অলস করে তোলে কারণ UI রাজ্যের একজন সংগ্রাহক থাকলেই রাষ্ট্র উৎপন্ন হয়।
এর UI এর জন্য অনন্য AuthorViewModel শুধুমাত্র লেখক নেভিগেশন গন্তব্যের জন্য প্রযোজ্য এবং অন্য কোথাও পুনরায় ব্যবহার করা যাবে না। যদি কোনো ব্যবসায়িক যুক্তি থাকে যা নেভিগেশন গন্তব্য জুড়ে পুনঃব্যবহৃত হয়, তাহলে সেই ব্যবসায়িক যুক্তিটিকে অবশ্যই একটি ডেটা- বা ডোমেন-লেয়ার-স্কোপড কম্পোনেন্টে এনক্যাপসুলেট করতে হবে।

একটি ব্যবসায়িক যুক্তি রাষ্ট্র ধারক হিসাবে ViewModel

অ্যান্ড্রয়েড ডেভেলপমেন্টে ViewModels-এর সুবিধাগুলি তাদের ব্যবসায়িক যুক্তিতে অ্যাক্সেস প্রদান এবং স্ক্রিনে উপস্থাপনের জন্য অ্যাপ্লিকেশন ডেটা প্রস্তুত করার জন্য উপযুক্ত করে তোলে। এই সুবিধাগুলির মধ্যে নিম্নলিখিতগুলি অন্তর্ভুক্ত রয়েছে:

UI লজিক এবং এর স্টেট হোল্ডার

UI লজিক হল লজিক যা UI নিজেই সরবরাহ করে এমন ডেটার উপর কাজ করে। এটি UI উপাদানগুলির অবস্থাতে বা অনুমতি API বা Resources মতো UI ডেটা উত্সগুলিতে হতে পারে৷ স্টেট হোল্ডার যারা UI লজিক ব্যবহার করে তাদের সাধারণত নিম্নলিখিত বৈশিষ্ট্য থাকে:

UI লজিক স্টেট হোল্ডার সাধারণত একটি প্লেইন ক্লাসের সাথে প্রয়োগ করা হয়। এর কারণ হল UI নিজেই UI লজিক স্টেট হোল্ডার তৈরির জন্য দায়ী এবং UI লজিক স্টেট হোল্ডারের UI এর মতোই একই জীবনচক্র রয়েছে। উদাহরণ স্বরূপ জেটপ্যাক কম্পোজে, স্টেট হোল্ডার কম্পোজিশনের অংশ এবং কম্পোজিশনের জীবনচক্র অনুসরণ করে।

পূর্ববর্তীটি এখন অ্যান্ড্রয়েড নমুনায় নিম্নলিখিত উদাহরণে চিত্রিত করা যেতে পারে:

এখন অ্যান্ড্রয়েডে ইউআই লজিক পরিচালনা করতে একটি প্লেইন ক্লাস স্টেট হোল্ডার ব্যবহার করে

চিত্র 5. The Now in Android নমুনা অ্যাপ।

Now in Android নমুনা ডিভাইসের স্ক্রিনের আকারের উপর নির্ভর করে এর নেভিগেশনের জন্য একটি নীচের অ্যাপ বার বা একটি নেভিগেশন রেল দেখায়৷ ছোট স্ক্রীনগুলি নীচের অ্যাপ বার এবং বড় স্ক্রীনগুলি নেভিগেশন রেল ব্যবহার করে৷

যেহেতু NiaApp কম্পোজেবল ফাংশনে ব্যবহৃত উপযুক্ত নেভিগেশন UI উপাদানের সিদ্ধান্ত নেওয়ার যুক্তি ব্যবসায়িক যুক্তির উপর নির্ভর করে না, তাই এটি NiaAppState নামক একটি প্লেইন ক্লাস স্টেট হোল্ডার দ্বারা পরিচালিত হতে পারে:

@Stable
class NiaAppState(
    val navController: NavHostController,
    val windowSizeClass: WindowSizeClass
) {

    // UI logic
    val shouldShowBottomBar: Boolean
        get() = windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact ||
            windowSizeClass.heightSizeClass == WindowHeightSizeClass.Compact

    // UI logic
    val shouldShowNavRail: Boolean
        get() = !shouldShowBottomBar

   // UI State
    val currentDestination: NavDestination?
        @Composable get() = navController
            .currentBackStackEntryAsState().value?.destination

    // UI logic
    fun navigate(destination: NiaNavigationDestination, route: String? = null) { /* ... */ }

     /* ... */
}

পূর্ববর্তী উদাহরণে, NiaAppState সম্পর্কিত নিম্নলিখিত বিবরণগুলি উল্লেখযোগ্য:

একটি স্টেট হোল্ডারের জন্য একটি ViewModel এবং প্লেইন ক্লাসের মধ্যে বেছে নিন

পূর্ববর্তী বিভাগগুলি থেকে, একটি ViewModel এবং একটি প্লেইন ক্লাস স্টেট হোল্ডারের মধ্যে নির্বাচন করা UI স্টেটে প্রয়োগ করা যুক্তি এবং লজিকটি পরিচালিত ডেটার উত্সগুলিতে নেমে আসে৷

সংক্ষেপে, নিম্নলিখিত চিত্রটি UI রাজ্য উত্পাদন পাইপলাইনে রাজ্য ধারকদের অবস্থান দেখায়:

ডেটা উৎপাদনকারী স্তর থেকে UI স্তরে ডেটা প্রবাহিত হয়

চিত্র 6. UI রাজ্য উত্পাদন পাইপলাইনে রাজ্য ধারক। তীর মানে ডেটা প্রবাহ।

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

রাষ্ট্রের ধারক চক্রবৃদ্ধিযোগ্য

রাষ্ট্র ধারক অন্যান্য রাষ্ট্র ধারকদের উপর নির্ভর করতে পারেন যতক্ষণ না নির্ভরতাগুলির সমান বা ছোট জীবনকাল থাকে। এর উদাহরণ হল:

নিম্নোক্ত কোড স্নিপেট দেখায় যে কীভাবে কম্পোজের DrawerState অন্য অভ্যন্তরীণ স্টেট হোল্ডার, SwipeableState উপর নির্ভর করে এবং কীভাবে একটি অ্যাপের UI লজিক স্টেট ধারক DrawerState উপর নির্ভর করতে পারে:

@Stable
class DrawerState(/* ... */) {
  internal val swipeableState = SwipeableState(/* ... */)
  // ...
}

@Stable
class MyAppState(
  private val drawerState: DrawerState,
  private val navController: NavHostController
) { /* ... */ }

@Composable
fun rememberMyAppState(
  drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
  navController: NavHostController = rememberNavController()
): MyAppState = remember(drawerState, navController) {
  MyAppState(drawerState, navController)
}

স্ক্রীন লেভেল স্টেট হোল্ডারের উপর নির্ভর করে একটি নির্ভরশীলতার উদাহরণ যা একজন স্টেট হোল্ডারকে UI লজিক স্টেট হোল্ডার হতে পারে। এটি স্বল্পকালীন রাষ্ট্র ধারকের পুনঃব্যবহারযোগ্যতা হ্রাস করবে এবং এটিকে প্রকৃতপক্ষে প্রয়োজনের চেয়ে আরও বেশি যুক্তি এবং রাষ্ট্রে অ্যাক্সেস দেবে।

যদি স্বল্পকালীন রাষ্ট্র ধারকের একটি উচ্চ-স্কোপযুক্ত রাষ্ট্র ধারকের কাছ থেকে নির্দিষ্ট তথ্যের প্রয়োজন হয়, তবে রাষ্ট্র ধারকের উদাহরণটি পাস করার পরিবর্তে একটি প্যারামিটার হিসাবে তার প্রয়োজনীয় তথ্যগুলি পাস করুন। উদাহরণস্বরূপ, নিম্নলিখিত কোড স্নিপেটে, UI লজিক স্টেট হোল্ডার ক্লাস নির্ভরতা হিসাবে পুরো ViewModel ইন্সট্যান্সকে পাস করার পরিবর্তে ViewModel থেকে প্যারামিটার হিসাবে যা প্রয়োজন তা পায়।

class MyScreenViewModel(/* ... */) {
  val uiState: StateFlow<MyScreenUiState> = /* ... */
  fun doSomething() { /* ... */ }
  fun doAnotherThing() { /* ... */ }
  // ...
}

@Stable
class MyScreenState(
  // DO NOT pass a ViewModel instance to a plain state holder class
  // private val viewModel: MyScreenViewModel,

  // Instead, pass only what it needs as a dependency
  private val someState: StateFlow<SomeState>,
  private val doSomething: () -> Unit,

  // Other UI-scoped types
  private val scaffoldState: ScaffoldState
) {
  /* ... */
}

@Composable
fun rememberMyScreenState(
  someState: StateFlow<SomeState>,
  doSomething: () -> Unit,
  scaffoldState: ScaffoldState = rememberScaffoldState()
): MyScreenState = remember(someState, doSomething, scaffoldState) {
  MyScreenState(someState, doSomething, scaffoldState)
}

@Composable
fun MyScreen(
  modifier: Modifier = Modifier,
  viewModel: MyScreenViewModel = viewModel(),
  state: MyScreenState = rememberMyScreenState(
    someState = viewModel.uiState.map { it.toSomeState() },
    doSomething = viewModel::doSomething
  ),
  // ...
) {
  /* ... */
}

নিম্নলিখিত চিত্রটি UI এবং পূর্ববর্তী কোড স্নিপেটের বিভিন্ন রাজ্য ধারকদের মধ্যে নির্ভরতা উপস্থাপন করে:

UI লজিক স্টেট হোল্ডার এবং স্ক্রীন লেভেল স্টেট হোল্ডার উভয়ের উপর নির্ভর করে

চিত্র 7. বিভিন্ন রাজ্য ধারকদের উপর নির্ভর করে UI। তীর মানে নির্ভরতা।

নমুনা

নিম্নলিখিত Google নমুনাগুলি UI স্তরে রাষ্ট্র ধারকদের ব্যবহার প্রদর্শন করে৷ অনুশীলনে এই নির্দেশিকা দেখতে তাদের অন্বেষণ করুন:

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

{% endverbatim %}

আপনার জন্য প্রস্তাবিত

{% endverbatim %}