טיפול בשגיאות באמצעות התכונה 'בקצרה'

החל מ-Android 15, יש תכונות API לשיפור הטיפול בשגיאות ב-Glance. בדף הזה מפורטות שיטות מומלצות לשימוש בממשקי ה-API האלה.

שימוש בבלוק try-catch סביב רכיבים שאינם קומפוזביליים

ב-Compose אי אפשר להשתמש בבלוקים של try-catch סביב פונקציות קומפוזביליות, אבל אפשר לעטוף את הלוגיקה האחרת של האפליקציה בבלוקים האלה. כך תוכלו להשתמש ב-Compose לתצוגת השגיאה, כמו בדוגמה הבאה:

provideContent {
    var isError = false
    var data = listOf<String>()
    try {
        val repository = (context.applicationContext as MyApplication).myRepository
        data = repository.loadData()
    } catch (e: Exception) {
        isError = true
        // TODO: handle error
    }

    if (isError) {
        ErrorView()
    } else {
        Content(data)
    }
}

פריסת ברירת המחדל של השגיאה

אם יש חריגה שלא נתפסה או שגיאה ב-Compose, ‏ Glance מציג פריסת שגיאה שמוגדרת כברירת מחדל:

הודעת שגיאה שמוצג בה סוג השגיאה והצעה איפה לחפש אותה
איור 1. פריסת ברירת המחדל של השגיאה ב-Glance 1.0
תיבה עם הטקסט &quot;לא ניתן להציג את התוכן&quot;
איור 2. פריסת ברירת המחדל של שגיאות ב-Glance 1.1.0

‫Glance מאפשר למפתחים לספק פריסת XML כחלופה אם הקומפוזיציה נכשלת. זה אומר שהייתה שגיאה בקוד של Compose. ממשק המשתמש של השגיאה הזו מופיע גם אם יש שגיאה שלא טופלה בקוד של האפליקציה.

class UpgradeWidget : GlanceAppWidget(errorUiLayout = R.layout.error_layout) {
    // ...
}
הפריסה הזו היא פריסה סטטית שהמשתמש לא יכול לבצע בה פעולות, אבל היא טובה למקרי חירום.

מכיל כותרת ושדה טקסט להצגת הודעת שגיאה
איור 3. דוגמה לפריסה מותאמת אישית של שגיאה

הוספת פעולות לממשק המשתמש של השגיאה שמוגדר כברירת מחדל

החל מגרסה 1.1.0 של Glance, אפשר לשנות את קוד הטיפול בשגיאות שמוגדר כברירת מחדל. כך אפשר להוסיף קריאות חוזרות (callbacks) לפעולות במקרה של חריגה שלא נתפסה או שגיאה בקומפוזיציה.

כדי להשתמש בתכונה הזו, צריך לשנות את הפונקציה onCompositionError():

GlanceAppWidget.onCompositionError(
    context: Context,
    glanceId: GlanceId,
    appWidgetId: Int,
    throwable: Throwable
)

בפונקציה הזו, Glance חוזר ל-API של RemoteViews כדי לטפל בשגיאות. כך אפשר לציין פריסות ורכיבי handler של פעולות באמצעות XML.

בדוגמאות הבאות מוסבר, שלב אחרי שלב, איך ליצור ממשק משתמש לשגיאות שכולל כפתור לשליחת משוב:

  1. כותבים את הקובץ error_layout.xml:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       style="@style/Widget.MyApplication.AppWidget.Error"
       android:id="@android:id/background"
       android:layout_width="match_parent"
       android:textSize="24sp"
       android:layout_height="match_parent"
       android:orientation="vertical">
    
       <TextView
           android:id="@+id/error_title_view"
           android:layout_width="match_parent"
           android:textColor="@color/white"
           android:textFontWeight="800"
           android:layout_height="wrap_content"
           android:text="Example Widget Error" />
    
       <LinearLayout
           android:layout_width="match_parent"
           android:orientation="horizontal"
           android:paddingTop="4dp"
           android:layout_height="match_parent">
    
           <ImageButton
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_gravity="center"
            android:tint="@color/white"
            android:id="@+id/error_icon"
            android:src="@drawable/heart_broken_fill0_wght400_grad0_opsz24"
           />
           <TextView
               android:id="@+id/error_text_view"
               android:layout_width="wrap_content"
               android:textColor="@color/white"
               android:layout_height="wrap_content"
               android:layout_gravity="center"
               android:padding="8dp"
               android:textSize="16sp"
               android:layout_weight="1"
               android:text="Useful Error Message!" />
       </LinearLayout>
    
    </LinearLayout>
    

  2. משנים את הפונקציה onCompositionError:

    override fun onCompositionError(
        context: Context, glanceId: GlanceId, appWidgetId: Int, throwable: Throwable
    ) {
        val rv = RemoteViews(context.packageName, R.layout.error_layout)
        rv.setTextViewText(
            R.id.error_text_view,
            "Error was thrown. \nThis is a custom view \nError Message: `${throwable.message}`"
        )
        rv.setOnClickPendingIntent(R.id.error_icon, getErrorIntent(context, throwable))
        AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, rv)
    }

    AppWidgetManager.updateAppWidget(appWidgetId, fallbackViews)
  3. יוצרים intent בהמתנה שמפנה אל GlanceAppWidgetReceiver:

    private fun getErrorIntent(context: Context, throwable: Throwable): PendingIntent {
        val intent = Intent(context, UpgradeToHelloWorldPro::class.java)
        intent.action = "widgetError"
        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
    }

  4. מטפלים ב-intent ב-GlanceAppWidgetReceiver:

    override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)
        Log.e("ErrorOnClick", "Button was clicked.")
    }