রচনায় UI অপরিবর্তনীয়—এটি আঁকার পরে এটি আপডেট করার কোনো উপায় নেই। আপনি যা নিয়ন্ত্রণ করতে পারেন তা হল আপনার UI এর অবস্থা। প্রতিবার UI এর অবস্থা পরিবর্তিত হলে, কম্পোজ UI ট্রির পরিবর্তিত অংশগুলিকে পুনরায় তৈরি করে । কম্পোজেবল স্টেট গ্রহণ করতে পারে এবং ইভেন্টগুলি প্রকাশ করতে পারে-উদাহরণস্বরূপ, একটি TextField
একটি মান গ্রহণ করে এবং onValueChange
একটি কলব্যাক প্রকাশ করে যা কলব্যাক হ্যান্ডলারকে মান পরিবর্তন করার জন্য অনুরোধ করে।
var name by remember { mutableStateOf("") } OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Name") } )
যেহেতু কম্পোজেবলগুলি স্টেট গ্রহণ করে এবং ঘটনাগুলি প্রকাশ করে, তাই একমুখী ডেটা প্রবাহ প্যাটার্ন জেটপ্যাক কম্পোজের সাথে ভালভাবে ফিট করে। এই নির্দেশিকাটি কম্পোজে কীভাবে একমুখী ডেটা প্রবাহের প্যাটার্ন বাস্তবায়ন করতে হয়, কীভাবে ইভেন্ট এবং স্টেট হোল্ডারগুলিকে বাস্তবায়ন করতে হয় এবং কম্পোজে ভিউমডেলগুলির সাথে কীভাবে কাজ করতে হয় তার উপর ফোকাস করে৷
একমুখী তথ্য প্রবাহ
একটি ইউনিডাইরেশনাল ডাটা ফ্লো (UDF) হল একটি ডিজাইন প্যাটার্ন যেখানে স্টেট নিচে প্রবাহিত হয় এবং ইভেন্টগুলি উপরে প্রবাহিত হয়। একমুখী ডেটা ফ্লো অনুসরণ করে, আপনি কম্পোজেবলগুলিকে ডিকপল করতে পারেন যা আপনার অ্যাপের অংশগুলি থেকে UI-তে স্থিতি দেখায় যা সংরক্ষণ করে এবং অবস্থা পরিবর্তন করে।
একমুখী ডেটা প্রবাহ ব্যবহার করে একটি অ্যাপের জন্য UI আপডেট লুপ দেখতে এইরকম:
- ইভেন্ট : UI এর অংশ একটি ইভেন্ট তৈরি করে এবং এটিকে ঊর্ধ্বমুখী করে, যেমন একটি বোতাম ক্লিক ভিউমডেল পরিচালনা করার জন্য পাস করা হয়; অথবা আপনার অ্যাপের অন্যান্য স্তর থেকে একটি ইভেন্ট পাস করা হয়েছে, যেমন ব্যবহারকারীর সেশনের মেয়াদ শেষ হয়ে গেছে।
- আপডেট অবস্থা : একটি ইভেন্ট হ্যান্ডলার রাষ্ট্র পরিবর্তন করতে পারে।
- ডিসপ্লে স্টেট : স্টেট হোল্ডার স্টেট থেকে চলে যায় এবং UI এটি প্রদর্শন করে।
![](https://developer.android.com/static/develop/ui/compose/images/state-unidirectional-flow.png?authuser=4&hl=bn)
জেটপ্যাক কম্পোজ ব্যবহার করার সময় এই প্যাটার্ন অনুসরণ করা বিভিন্ন সুবিধা প্রদান করে:
- পরীক্ষাযোগ্যতা : UI থেকে ডিকপলিং স্টেট যা প্রদর্শন করে তা বিচ্ছিন্নভাবে উভয় পরীক্ষা করা সহজ করে তোলে।
- স্টেট এনক্যাপসুলেশন : যেহেতু স্টেট শুধুমাত্র একটি জায়গায় আপডেট করা যায় এবং একটি কম্পোজেবল স্টেটের জন্য সত্যের একটি মাত্র উৎস আছে, তাই অসামঞ্জস্যপূর্ণ অবস্থার কারণে আপনি বাগ তৈরি করার সম্ভাবনা কম।
- UI সামঞ্জস্যতা :
StateFlow
বাLiveData
এর মতো পর্যবেক্ষণযোগ্য স্টেট হোল্ডার ব্যবহার করে সমস্ত স্টেট আপডেট অবিলম্বে UI-তে প্রতিফলিত হয়।
জেটপ্যাক রচনায় একমুখী ডেটা প্রবাহ
কম্পোজেবলগুলি রাষ্ট্র এবং ঘটনাগুলির উপর ভিত্তি করে কাজ করে। উদাহরণস্বরূপ, একটি TextField
শুধুমাত্র তখনই আপডেট হয় যখন এর value
প্যারামিটার আপডেট করা হয় এবং এটি একটি onValueChange
কলব্যাক প্রকাশ করে—একটি ইভেন্ট যা মানটিকে একটি নতুন তে পরিবর্তন করার অনুরোধ করে। কম্পোজ State
অবজেক্টকে একটি মান ধারক হিসাবে সংজ্ঞায়িত করে এবং রাষ্ট্রীয় মানের পরিবর্তন একটি পুনর্গঠনকে ট্রিগার করে। আপনি কতক্ষণের জন্য মানটি মনে রাখতে হবে তার উপর নির্ভর করে আপনি একটি remember { mutableStateOf(value) }
বা একটি rememberSaveable { mutableStateOf(value)
তে স্টেট ধরে রাখতে পারেন৷
TextField
কম্পোজেবলের মান হল String
, তাই এটি যেকোনো জায়গা থেকে আসতে পারে—হার্ডকোড করা মান থেকে, ভিউমডেল থেকে, অথবা প্যারেন্ট কম্পোজেবল থেকে পাস করা যেতে পারে। আপনাকে এটিকে State
অবজেক্টে ধরে রাখতে হবে না, তবে যখন onValueChange
কল করা হয় তখন আপনাকে মানটি আপডেট করতে হবে।
কম্পোজেবল প্যারামিটার সংজ্ঞায়িত করুন
একটি কম্পোজেবলের স্টেট প্যারামিটারগুলি সংজ্ঞায়িত করার সময় আপনাকে নিম্নলিখিত প্রশ্নগুলি মনে রাখা উচিত:
- কম্পোজেবল কতটা পুনর্ব্যবহারযোগ্য বা নমনীয়?
- কিভাবে রাষ্ট্র পরামিতি এই কম্পোজেবল এর কর্মক্ষমতা প্রভাবিত করে?
ডিকপলিং এবং পুনঃব্যবহারকে উত্সাহিত করার জন্য, প্রতিটি কম্পোজেবলের সম্ভাব্য সর্বনিম্ন পরিমাণ তথ্য রাখা উচিত। উদাহরণস্বরূপ, একটি সংবাদ নিবন্ধের শিরোনাম ধরে রাখার জন্য একটি কম্পোজেবল তৈরি করার সময়, সম্পূর্ণ সংবাদ নিবন্ধের পরিবর্তে শুধুমাত্র সেই তথ্যগুলিকে পাস করতে পছন্দ করুন যা প্রদর্শন করা প্রয়োজন:
@Composable fun Header(title: String, subtitle: String) { // Recomposes when title or subtitle have changed. } @Composable fun Header(news: News) { // Recomposes when a new instance of News is passed in. }
কখনও কখনও, স্বতন্ত্র পরামিতি ব্যবহার করা কর্মক্ষমতাকেও উন্নত করে-উদাহরণস্বরূপ, যদি News
শুধুমাত্র title
এবং subtitle
ছাড়া আরও তথ্য থাকে, যখনই News
এর একটি নতুন উদাহরণ Header(news)
-এ পাস করা হয়, তাহলে কম্পোজেবলটি পুনরায় কম্পোজ করবে, এমনকি title
এবং subtitle
না থাকলেও পরিবর্তিত
আপনার পাস করা প্যারামিটারের সংখ্যা সাবধানতার সাথে বিবেচনা করুন৷ অনেকগুলি পরামিতি সহ একটি ফাংশন থাকলে ফাংশনের ergonomics হ্রাস পায়, তাই এই ক্ষেত্রে সেগুলিকে একটি শ্রেণিতে গোষ্ঠীবদ্ধ করা পছন্দনীয়৷
রচনা ইভেন্ট
আপনার অ্যাপের প্রতিটি ইনপুট একটি ইভেন্ট হিসাবে উপস্থাপন করা উচিত: ট্যাপ, পাঠ্য পরিবর্তন এবং এমনকি টাইমার বা অন্যান্য আপডেট। যেহেতু এই ইভেন্টগুলি আপনার UI এর অবস্থাকে পরিবর্তন করে, তাই ViewModel
হতে হবে সেগুলিকে পরিচালনা করবে এবং UI অবস্থা আপডেট করবে৷
UI স্তরটি কখনই কোনও ইভেন্ট হ্যান্ডলারের বাইরের অবস্থা পরিবর্তন করা উচিত নয় কারণ এটি আপনার অ্যাপ্লিকেশনে অসঙ্গতি এবং বাগগুলি প্রবর্তন করতে পারে।
রাষ্ট্র এবং ইভেন্ট হ্যান্ডলার ল্যাম্বডাসের জন্য অপরিবর্তনীয় মান পাস করা পছন্দ করুন। এই পদ্ধতির নিম্নলিখিত সুবিধা রয়েছে:
- আপনি পুনর্ব্যবহারযোগ্যতা উন্নত করুন।
- আপনি নিশ্চিত করুন যে আপনার UI সরাসরি রাষ্ট্রের মান পরিবর্তন করে না।
- আপনি কনকারেন্সি সমস্যাগুলি এড়িয়ে যান কারণ আপনি নিশ্চিত করেন যে রাজ্যটি অন্য থ্রেড থেকে মিউট করা হয়নি।
- প্রায়শই, আপনি কোড জটিলতা হ্রাস করেন।
উদাহরণস্বরূপ, একটি কম্পোজেবল যা একটি String
এবং একটি ল্যাম্বডাকে পরামিতি হিসাবে গ্রহণ করে অনেক প্রসঙ্গ থেকে কল করা যেতে পারে এবং এটি অত্যন্ত পুনঃব্যবহারযোগ্য। ধরুন আপনার অ্যাপের উপরের অ্যাপ বারে সবসময় টেক্সট দেখায় এবং একটি ব্যাক বোতাম থাকে। আপনি আরও জেনেরিক MyAppTopAppBar
কম্পোজেবল সংজ্ঞায়িত করতে পারেন যা পাঠ্য এবং ব্যাক বোতাম হ্যান্ডেলকে পরামিতি হিসাবে গ্রহণ করে:
@Composable fun MyAppTopAppBar(topAppBarText: String, onBackPressed: () -> Unit) { TopAppBar( title = { Text( text = topAppBarText, textAlign = TextAlign.Center, modifier = Modifier .fillMaxSize() .wrapContentSize(Alignment.Center) ) }, navigationIcon = { IconButton(onClick = onBackPressed) { Icon( Icons.Filled.ArrowBack, contentDescription = localizedString ) } }, // ... ) }
মডেল, রাজ্য এবং ঘটনা দেখুন: একটি উদাহরণ
ViewModel
এবং mutableStateOf
ব্যবহার করে, আপনি আপনার অ্যাপে একমুখী ডেটা প্রবাহ চালু করতে পারেন যদি নিম্নলিখিতগুলির মধ্যে একটি সত্য হয়:
-
StateFlow
বাLiveData
এর মতো পর্যবেক্ষণযোগ্য স্টেট হোল্ডারের মাধ্যমে আপনার UI-এর অবস্থা প্রকাশ করা হয়। -
ViewModel
আপনার অ্যাপের UI বা অন্যান্য স্তর থেকে আসা ইভেন্টগুলি পরিচালনা করে এবং ইভেন্টগুলির উপর ভিত্তি করে স্টেট হোল্ডার আপডেট করে৷
উদাহরণস্বরূপ, একটি সাইন-ইন স্ক্রীন প্রয়োগ করার সময়, একটি সাইন ইন বোতামে আলতো চাপলে আপনার অ্যাপটি একটি অগ্রগতি স্পিনার এবং একটি নেটওয়ার্ক কল প্রদর্শন করবে৷ যদি লগইন সফল হয়, তাহলে আপনার অ্যাপটি একটি ভিন্ন স্ক্রিনে নেভিগেট করবে; কোনো ত্রুটির ক্ষেত্রে অ্যাপটি একটি স্ন্যাকবার দেখায়। আপনি কীভাবে পর্দার অবস্থা এবং ইভেন্টের মডেল করবেন তা এখানে:
পর্দার চারটি অবস্থা রয়েছে:
- সাইন আউট : যখন ব্যবহারকারী এখনও সাইন ইন করেননি।
- প্রগতিতে : যখন আপনার অ্যাপ বর্তমানে একটি নেটওয়ার্ক কল করে ব্যবহারকারীকে সাইন ইন করার চেষ্টা করছে।
- ত্রুটি : যখন সাইন ইন করার সময় একটি ত্রুটি ঘটেছে৷
- সাইন ইন করেছেন : যখন ব্যবহারকারী সাইন ইন করেন।
আপনি একটি সিল ক্লাস হিসাবে এই রাজ্যগুলি মডেল করতে পারেন. ViewModel
রাজ্যটিকে একটি State
হিসাবে প্রকাশ করে, প্রাথমিক অবস্থা সেট করে এবং প্রয়োজন অনুসারে রাষ্ট্রকে আপডেট করে। ViewModel
এছাড়াও একটি onSignIn()
পদ্ধতি প্রকাশ করে সাইন-ইন ইভেন্ট পরিচালনা করে।
class MyViewModel : ViewModel() { private val _uiState = mutableStateOf<UiState>(UiState.SignedOut) val uiState: State<UiState> get() = _uiState // ... }
mutableStateOf
API ছাড়াও, কম্পোজ LiveData
, Flow
, এবং Observable
শ্রোতা হিসাবে নিবন্ধন করতে এবং একটি রাষ্ট্র হিসাবে মান উপস্থাপন করার জন্য এক্সটেনশন সরবরাহ করে ।
class MyViewModel : ViewModel() { private val _uiState = MutableLiveData<UiState>(UiState.SignedOut) val uiState: LiveData<UiState> get() = _uiState // ... } @Composable fun MyComposable(viewModel: MyViewModel) { val uiState = viewModel.uiState.observeAsState() // ... }
আরও জানুন
জেটপ্যাক কম্পোজে আর্কিটেকচার সম্পর্কে আরও জানতে, নিম্নলিখিত সংস্থানগুলি দেখুন:
নমুনা
আপনার জন্য প্রস্তাবিত
- দ্রষ্টব্য: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট প্রদর্শিত হয়
- রাজ্য এবং জেটপ্যাক রচনা
- রচনায় UI অবস্থা সংরক্ষণ করুন
- ব্যবহারকারীর ইনপুট পরিচালনা করুন