استفاده از Remember و State ها در JetpackCompose

دراین بخش قصد دارم نحوه ی استفاده از state هارا برای شما توضیح بدهم این مبحث فوق العاده کاربردی ومهم هست.ما تازمانی که محتوای static داشته باشیم نیازی به state ها نداریم چون دراین صورت محتوای ما نیازی به تغییر ندارد اما در اپلیکیشن ها معمولا به محتوای داینامیک نیاز است بنابراین ما نیاز داریم که درصورت انجام کاری در اپ تغییری ببینیم بهتر است از ابتدا با مفهوم recompose اشنا شویم :مفهوم Recomposition:بازترکیب یا Re composition فرآیند فراخوانی مجدد توابعی که با @Composable حاشیه نویسی شده اند راانجام میدهد این موضوع زمانی اتفاق می افتد که حالت ها یا state ها تغییر کنند. وقتی Compose بر اساس حالت های جدید دوباره ساخته می شود را recomposition یابازترکیب می گویند،دراین فرایند فقط توابع یا لامبداهایی که ممکن است تغییر کرده باشند فراخوانی می‌ شوند و بقیه فراخوانی نمی‌شوند.فرض کنید یک اپلیکیشن شمارنده داریم به این صورت که بر روی یک دکمه کلیک می کنیم و مقدار عدد روی دکمه زیاد می شود هربار که روی دکمه میزنیم درواقع UIمربوط به دکمه ی ما دوباره ساخته می شود که به اصطلاح Redraw می شود و عدد جدید روی دکمه نمایش داده می شود به این فرایند Recompose می گویند که همان redrawیا rerun است.حالا به مثال زیر توجه کنید:فرض کنید یک دکمه داریم و میخواهیم بازدن روی این دکمه رنگ ان تغییر کند برای اینکار ابتدایک تابع Composable به اسم Color Box تعریف می کنیم قصد داریم کل پیاده سازی دکمه ی گفته شده دراین تابع باشد:سپس دراین تابع یک Box تعریف میکنیم:تابع clickable{} به این خاطر تعریف می شود که Box مثل یک دکمه عمل کند و بتوان روی ان click کرد.پیاده سازی Stateکامپوز اعلانی است و به این ترتیب تنها راه برای به روز رسانی آن فراخوانی همان تابع composable با آرگومان های جدید است. این آرگومان ها نمایش هایی از وضعیت رابط کاربری هستند. هر زمان که وضعیتی به روز می شود، composeمجدد صورت می گیرد. در نتیجه، چیزهایی مانند TextField به طور خودکار مثل عملکرد XML به روز نمی شوند. به یک composable باید به صراحت وضعیت جدید گفته شود تا مطابق آن بروز شود.حالت یا state شیئی است که به یک یا چند ویجت متصل است، حاوی داده است و مشتاق به روز رسانی ویجت ها از آن داده است. اگر تغییری در داده‌ها اتفاق بیفتد، به همه ویجت‌هایی که به آنها متصل است اطلاع می‌دهد.در jetpack compose مفهوم مدیریت stateهمان Observable pattern است که بیان می‌کند اگر تغییری در شیء تعریف شده رخ دهد، تمام اشیاء وابسته به آن را به طور خودکارتغییر می دهد.برای استفاده ازstate ها از MutableState استفاده می کنیم:interface MutableState<T> : State<T> { override var value: T }خب به مثالمون برمی گردیم همانطور که گفتیم باید باهربار کلیک روی Box رنگ پس زمینه ی ان تغییر کند پس نباید به ان رنگ ثابت دهیم به این ترتیب یک state تعریف می کنیم ومقدار ان را به background میدهیم:در گذشته به جای mutableStateOf، از حاشیه‌نویسی Model @ استفاده می‌کردیم، اما درنسخه ی 0.1.0-dev12 منسوخ شد. سپس state{} درنسخه ی 0.1.0-dev16 منسوخ شد.سپس در داخل تابع clickable هربار که روی Box کلیک کنیم مقدار این state مربوط به color را اپدیت می کنیم وبه متغیر color می دهیم:همانطور که مشاهده می کنید تابع تعریف شده ی Color سه مقدار قرمز و سبز و ابی دارد که به انها بصورت رندوم مقدارمی دهیم و درنهایت مقدار خروجی را به متغیرcolor می دهیم.هربار که مقدار این color که از نوع mutableState است تغییر می کند تابع Color Box دوباره برروی UIساخته می شود و Redrawیا به عبارتی recompose می شودپس به این ترتیب تمامی متغیر ها وتوابعی که در Color Box فراخوانی شده اند دوباره فراخوانی می شوند به این ترتیب تابع background دوباره مقدار جدید را دریافت میکند و رنگ Box تغییر میکند.مشکل پاراگراف قبل چیست؟همانطور که گفتیم در طی recompose تمامی متغیرها و توابع دوباره فراخوانی می شوند همانطور که در کد مشاهده می کنیددر طی recompose تابع colorBoxدر ابتدای به متغیر color مقدار پیش فرض زرد داده می شود پس دوباره مقدار زرد را به خود می گیرد و مقدار رندومی که قبلا ساخته شده بود از بین می رودو background دوباره بعد از هر بار کلیک به رنگ زرد در می اید !راه حل چیست؟استفاده از rememberتوابع Composable می توانند با استفاده از remember یک شی را در حافظه ذخیره کنند. stateموجود داخل remember بعد ازاینکه در ادامه ی کد مقداری می گیرد ان را درون حافظه ذخیره می کند و در طی recompose همان مقدار ذخیره شده درحافظه برگردانده می شود .در این قسمت remember به کمک ما می اید:همانطور که مشاهده می کنید متغیر color رادرون remember قرار دادیم که همانطور که از اسمش پیداست بعد از هر بار recompose مقدار قبلی متغیر colorرابه خاطر می سپارد ودرحافظه ذخیره می کند و باعث می شود متغیر دوباره مقدار پیش فرض را به خود نگیرد در این صورت مشکل ما حل میشود:به این صورت بعد از هربار کلیک رنگ Box تغییر میکند.کدنوشته شده دربالا به صورت زیراست:class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ColorBox(Modifier.fillMaxSize()) } } } @Composable fun ColorBox(modifier: Modifier = Modifier) { val color = remember { mutableStateOf(value = Color.Yellow) } Box(modifier = modifier .background(color.value) .clickable { color.value = Color( red = Random.nextFloat(), green = Random.nextFloat(), blue = Random.nextFloat() ) } ) { } }امیدوارم مفید بوده باشه موفق باشید.