StateStore بخشی از Android Jetpack.
StateStore محفظهای با ایمنی تایپی است که وضعیت برنامه همرسانیشده را بهصورت Compose State در سراسر برنامه شما ذخیره و نمایش میدهد.
موارد استفاده
با ایجاد StateStore با دامنه برنامه، میتوانید وضعیت را بین مؤلفههای برنامه در همان فرایند همرسانی کنید:
- فعالیتهای متعدد: اگر برنامه شما چندین فعالیت را بهطور همزمان نمایش میدهد (مانند فعالیت صندوق ورودی و فعالیت ویرایشگر در یک کارخواه ایمیل) یا فعالیتی دارد که از چندنمونهای پشتیبانی میکند (مانند فعالیت نمایشگر سند)، میتوانید از
StateStoreبرای همرسانی اطلاعات بین آنها استفاده کنید. - فعالیت و سرویس: همگامسازی وضعیت بین یک فعالیت و یک
CarAppServiceپسزمینه یا AppFunction. - ارائهدهنده فعالیت و محتوا یا ابزاره: همرسانی وضعیت بین یک فعالیت و ابزاره صفحه اصلی.
اگر یک تکقلو فقط به State<T> درون حافظه بدون جستجوی کلیددار یا
بازیابی مرگ پردازش با پشتیبانی DataStore نیاز دارد، میتوانید بهجای آن ویژگیهای mutableStateOf را
مستقیماً در تکقلو نمایش دهید. برای مقایسه میاناهای برنامهسازی کاربردی وضعیت
در سراسر برنامهتان، انتخاب میانای برنامهسازی کاربردی وضعیت مناسب در سراسر
معماری را ببینید.
نمای کلی میانای برنامهسازی کاربردی
بسته androidx.appstate.statestore کلاسهای StateStore و
StateStoreKey را ارائه میدهد:
package androidx.appstate.statestore
import androidx.compose.runtime.State
import kotlinx.serialization.Serializable
public class StateStore {
public val keys: Set<StateStoreKey<*>>
public fun <T> getState(
stateKey: StateStoreKey<T>,
defaultValue: T = stateKey.defaultValue,
): State<T>
public fun <T> setState(stateKey: StateStoreKey<T>, value: T)
public inline fun <T> updateState(
stateKey: StateStoreKey<T>,
defaultValue: T = stateKey.defaultValue,
update: (T) -> T,
)
}
@Serializable
public open class StateStoreKey<T>(
public val defaultValue: T,
)
تعریف کردن ایالت
برای اطمینان از ایمنی تایپی هنگام ذخیره و بازیابی مقادیر، StateStore از کلاس
StateStoreKey برای تعریف کلیدهای مورداستفاده برای خواندن و نوشتن مقادیر استفاده میکند. تعاریف StateStoreKey private یا internal را برای مدیر، مخزن،
یا ماژولی که مالک آن بخش از وضعیت است نگه دارید:
@Serializable sealed interface FocusSession { @Serializable data object Idle : FocusSession @Serializable data class Running( val taskId: String, val endTimeMillis: Long, ) : FocusSession @Serializable data class Paused( val taskId: String, val remainingMillis: Long, ) : FocusSession } @Serializable private data object FocusSessionKey : StateStoreKey<FocusSession>(defaultValue = FocusSession.Idle)
ایجاد و تزریق نمونههای StateStore
StateStore یک کلاس معمولی است که یک بار در محدوده برنامه یا ماژول نمونهسازی میکنید (برای مثال، در کلاس Application یا ماژول تزریق وابستگی) و به مدیران یا مخازنی که وضعیت را میخوانند و مینویسند تزریق میکنید، بهجای اینکه StateStore را مستقیماً در کلاسهای UI نمایش دهید:
// Instantiate at the application or DI module level val stateStore = StateStore() // Inject into managers or repositories that encapsulate their own keys class FocusSessionManager( private val stateStore: StateStore, )
وضعیت خواندن و نوشتن
در مدیر یا مخزن خود، مقادیر را در StateStore تزریقشده بااستفاده از تعاریف StateStoreKey خصوصی خود بخوانید، بنویسید، و بهروز کنید، و ویژگیهای فقط خواندنی State<T> و توابع جهش را برای تماسگیرندگان نمایش دهید.
وضعیت خوانده شدن
از getState(stateKey, defaultValue) برای بازیابی شیء State<T> استفاده کنید. اگر کلید هنوز مقداردهی اولیه نشده باشد، StateStore آن را با پارامتر defaultValue پر میکند که بهطور پیشفرض stateKey.defaultValue است (یا میتوانید هنگام مقداردهی اولیه کلید پرنشده، defaultValue سفارشی را ارسال کنید). چون
getState یک State<T> برمیگرداند، ViewModels، UI composables، ابزارهها، و
بلوکهای transform میتوانند ویژگی مدیر را بهصورت واکنشی بخوانند:
class FocusSessionManager( private val stateStore: StateStore, ) { val session: State<FocusSession> = stateStore.getState(FocusSessionKey) } class FocusTimerViewModel( focusSessionManager: FocusSessionManager, ) : ViewModel() { val session: State<FocusSession> = focusSessionManager.session } @Composable fun FocusBanner(viewModel: FocusTimerViewModel = viewModel()) { // Reads state reactively; recomposes when FocusSessionKey updates when (val session = viewModel.session.value) { FocusSession.Idle -> Text(text = "No active focus session") is FocusSession.Running -> Text(text = "Focusing on ${session.taskId}") is FocusSession.Paused -> Text(text = "Paused: ${session.taskId}") } }
نوشتن ایالت
از setState(stateKey, value) در مدیرتان برای مقداردهی اولیه یا جایگزینی
مقدار مرتبط با کلید استفاده کنید:
class FocusSessionManager( private val stateStore: StateStore, ) { val session: State<FocusSession> = stateStore.getState(FocusSessionKey) fun startFocus(taskId: String, endTimeMillis: Long) { stateStore.setState( FocusSessionKey, FocusSession.Running( taskId = taskId, endTimeMillis = endTimeMillis, ), ) } fun endFocus() { stateStore.setState(FocusSessionKey, FocusSession.Idle) } }
بهروزرسانی وضعیت
اگر لازم است وضعیتی را براساس مقدار فعلی آن بهروز کنید، از updateState استفاده کنید.
این کار مقدار فعلی را بازیابی میکند (یا اگر تنظیم نشده باشد، از مقدار پیشفرض استفاده میکند) و
لامبدای بهروزرسانی شما را اعمال میکند:
class FocusSessionManager( private val stateStore: StateStore, ) { val session: State<FocusSession> = stateStore.getState(FocusSessionKey) fun pauseFocus(nowMillis: Long) { stateStore.updateState(FocusSessionKey) { current -> if (current is FocusSession.Running) { FocusSession.Paused( taskId = current.taskId, remainingMillis = (current.endTimeMillis - nowMillis) .coerceAtLeast(0L), ) } else { current } } } fun resumeFocus(nowMillis: Long) { stateStore.updateState(FocusSessionKey) { current -> if (current is FocusSession.Paused) { FocusSession.Running( taskId = current.taskId, endTimeMillis = nowMillis + current.remainingMillis, ) } else { current } } } }
یکپارچگی
StateStore با Jetpack DataStore ادغام میشود تا وضعیت را درطول مرگ پردازش و بازراهاندازی برنامه حفظ و بازیابی کند.
DataStore
آرتیفکت androidx.appstate.statestore:statestore-datastore به شما امکان میدهد
پایداری را یکبار در نمونه StateStore مشترک خود پیکربندی کنید تا کلیدهای پایدار هر
مدیر بهطور خودکار بااستفاده از DataStore در دیسک ذخیره و بازیابی شود.
بسته androidx.appstate.datastore میاناهای برنامهسازی کاربردی زیر را ارائه میدهد:
package androidx.appstate.datastore
import androidx.appstate.statestore.StateStore
import androidx.datastore.core.DataStore
import kotlinx.coroutines.CoroutineScope
public interface PersistToDataStore
public suspend fun StateStore.syncToDataStore(
path: String,
coroutineScope: CoroutineScope,
)
public suspend fun StateStore.syncToDataStore(
dataStore: DataStore<StateStorePreferences>,
)
- پیادهسازی
PersistToDataStore: هرStateStoreKeyرا که باید با پیادهسازی میانایPersistToDataStoreحفظ شود علامتگذاری کنید:
@Serializable private data object FocusSessionKey : StateStoreKey<FocusSession>(defaultValue = FocusSession.Idle), PersistToDataStore
- Bind
StateStoreto DataStore: CallsyncToDataStoreonce when setting up your sharedStateStoreinstance (for example, in yourApplicationclass or dependency injection module). چونsyncToDataStoreیک تابعsuspendاست که بهطور نامحدود تعلیق میشود تا مقادیر ذخیرهشده را از دیسک بازیابی کند و به ذخیره کردن تغییرات آتی درcoroutineScopeارائهشده ادامه دهد، آن را درlaunchفراخوانی کنید وCoroutineScopeسطح برنامهتان را ارسال کنید. در زمان راهاندازی،getStateدر ابتداdefaultValueرا در حافظه برمیگرداند و پساز اینکه DataStore خواندن از دیسک را تمام کرد،Stateرا بهروز میکند:
class ProductivityApplication : Application() { val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) val stateStore = StateStore().also { store -> // Restore saved values and automatically persist future changes // for all PersistToDataStore keys across managers applicationScope.launch { store.syncToDataStore( path = dataStoreFile("statestore.json").absolutePath, coroutineScope = applicationScope, ) } } val focusSessionManager = FocusSessionManager(stateStore) }
دستورالعملهای پایداری DataStore
چون syncToDataStore هرگاه مقدار کلید PersistToDataStore تغییر کند، آن را سریالسازی میکند و در دیسک مینویسد، هنگام انتخاب اینکه چه چیزی و چه زمانی پایدار بماند، این دستورالعملها را دنبال کنید:
- مُهرهای زمان شروع یا پایان را بهجای هر تیک زمانسنج ذخیره کنید: برای زمانسنجها یا
پیشرفت بازپخش، بهجای بهروزرسانی کلید
PersistToDataStoreدر هر ثانیه یا فریم، مقدار مرجع پایداری (مانندendTimeMillisیاstartedAtMillis) را حفظ کنید و نمایش زنده زمان سپریشده یا باقیمانده را در واسط کاربر محاسبه کنید. - قبلاز بهروزرسانی کلید ماندگار، ورودی سریع کاربر را لرزشگیری کنید: برای پیشنویسهای نوشتاری، پُرسمانهای جستجو، یا لغزندهها، ورودی فوری را در یک
MutableStateدرونحافظهای (یا یکStateStoreKeyکهPersistToDataStoreرا پیادهسازی نمیکند) نگه دارید و فقط پساز تثبیت ورودی،setStateرا رویStateStoreKeyماندگار فراخوانی کنید. - سبک نگه داشتن کلیدهای ماندگار: همه کلیدهای
PersistToDataStoreدر یکStateStoreدر هر بهروزرسانی باهم در یک فایل واحد سریالسازی میشوند. وضعیت جلسه فشرده را حفظ کنید—مانند شناسههای فعال، انتخابهای فیلتر، یا پیشنویسهای فرم درحال انجام—و مجموعههای بزرگ یا مجموعهدادههای قابلپرسوجو را در Room نگه دارید.