0Pricing
Kotlin Academy · درس

نمذجة حالة واجهة المستخدم باستخدام Sealed Classes

طبّق sealed classes لتمثيل حالات واجهة المستخدم Loading وSuccess وError.

نمذجة حالة واجهة المستخدم باستخدام Sealed Classes درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

مشكلة حالة واجهة المستخدم

تحتوي شاشات واجهة المستخدم على حالات متعددة: التحميل، وعرض البيانات، وعرض خطأ، أو كونها فارغة. وتُعد إدارة هذه الحالات باستخدام القيم المنطقية (isLoading وhasError) هشة. تحل الفئات sealed هذه المشكلة.

جحيم القيم المنطقية التقليدي

يؤدي استخدام قيم منطقية منفصلة إلى حالات مستحيلة.
// Fragile: isLoading=true AND hasError=true is invalid
var isLoading = false
var hasError = false
var data: List<Item>? = null
// 8 combinations, most of which are invalid!

حالة sealed: حالات صالحة فقط

تجعل sealed class الحالات غير الصالحة غير قابلة للتمثيل.
sealed class UiState<out T>
object Loading : UiState<Nothing>()
data class Success<T>(val data: T) : UiState<T>()
data class Error(val message: String, val retryable: Boolean = true) : UiState<Nothing>()
object Empty : UiState<Nothing>()

العرض بناءً على الحالة

استخدموا when لعرض واجهة المستخدم الصحيحة لكل حالة.
fun render(state: UiState<List<Item>>) = when (state) {
    Loading -> showProgressBar()
    is Success -> showItems(state.data)
    is Error -> showError(state.message, state.retryable)
    Empty -> showEmptyView()
}

إصدار ViewModel للحالات

يُصدر ViewModel حالات sealed عبر StateFlow.
class ItemViewModel : ViewModel() {
    private val _state = MutableStateFlow<UiState<List<Item>>>(Loading)
    val state: StateFlow<UiState<List<Item>>> = _state

    fun loadItems() = viewModelScope.launch {
        _state.value = Loading
        _state.value = try {
            Success(repository.getItems())
        } catch (e: Exception) {
            Error(e.message ?: "Unknown error")
        }
    }
}

تركيب الحالات مع المحتوى داخلها

استخدموا حالات sealed عامة للتعامل مع أي نوع من البيانات.
fun <T> loading(): UiState<T> = Loading
fun <T> success(data: T): UiState<T> = Success(data)
fun <T> error(msg: String): UiState<T> = Error(msg)

مثال على حالة الترقيم الصفحي

تمثّل الفئات sealed حالات القوائم المرقّمة صفحيًا بصورة طبيعية.
sealed class PageState
object Idle : PageState()
object FirstLoad : PageState()
data class Content(val items: List<Item>, val hasMore: Boolean) : PageState()
data class LoadingMore(val items: List<Item>) : PageState()
data class Error(val items: List<Item>?, val msg: String) : PageState()

تحويل الحالة

حوّلوا الحالات الناجحة دون المساس بالحالات الأخرى.
fun <T, R> UiState<T>.mapData(transform: (T) -> R): UiState<R> = when (this) {
    is Success -> Success(transform(data))
    is Error -> this
    Loading -> Loading
    Empty -> Empty
}

الاختبار باستخدام حالات sealed

من السهل اختبار الحالات — ما عليكم سوى التحقق من المتغير الذي تم إصداره.
@Test
fun testLoadingState() {
    viewModel.loadItems()
    assertEquals(Loading, viewModel.state.value)
}
@Test
fun testSuccessState() {
    viewModel.setData(listOf(item))
    assert(viewModel.state.value is Success)
}

حالة مدمجة أم تدفقات متعددة

يكون تدفق حالة sealed واحد أوضح من عدة تدفقات منفصلة يجب أن تبقى متزامنة.
// Fragile: two flows must stay in sync
val loading = MutableStateFlow(false)
val error = MutableStateFlow<String?>(null)

// Clean: one sealed state
val state = MutableStateFlow<UiState<List<Item>>>(Loading)

إضافة بيانات وصفية إلى الحالات

يمكن للأنواع الفرعية sealed حمل البيانات الوصفية ذات الصلة.
data class Error(
    val message: String,
    val code: Int = 0,
    val retryable: Boolean = true,
    val timestamp: Long = System.currentTimeMillis()
) : UiState<Nothing>()

تحقق سريع

ما المشكلة الرئيسية التي يحلها نمذجة حالة واجهة المستخدم باستخدام الفئات sealed؟

مراجعة

نمذجوا حالة واجهة المستخدم باستخدام الفئات sealed: Loading وSuccess(data) وError(message) وEmpty. استخدموا when لعرض كل حالة. ويُعد StateFlow واحد من النوع sealed أفضل من عدة أعلام منطقية. التالي: تداخل التسلسلات الهرمية sealed!

الأسئلة الشائعة

هل درس «نمذجة حالة واجهة المستخدم باستخدام Sealed Classes» مجاني؟

نعم — نص درس «نمذجة حالة واجهة المستخدم باستخدام Sealed Classes» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ماذا ستتعلم في «نمذجة حالة واجهة المستخدم باستخدام Sealed Classes»؟

طبّق sealed classes لتمثيل حالات واجهة المستخدم Loading وSuccess وError. تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟

لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «نمذجة حالة واجهة المستخدم باستخدام Sealed Classes»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟

نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. ‏sealed class مقابل sealed interface: متى تستخدم كلًّا منهما
  2. ‏when شامل مع التسلسلات الهرمية المختومة
  3. نمذجة حالة واجهة المستخدم باستخدام Sealed Classes
  4. تداخل التسلسلات الهرمية المختومة ودمجها
← العودة إلى Kotlin Academy