使用 Glance 处理错误

自 Android 15 起,Glance 中包含用于改进错误处理的 API 功能。本页提供了有关这些 API 的最佳实践。

在不可组合的组件周围使用 try-catch 块

Compose 不允许在可组合函数周围使用 try-catch 块,但允许您将应用的其他逻辑封装在这些块中。这样一来,您就可以使用 Compose 创建错误视图,如以下示例所示:

provideContent {  var isError = false;  var data = null  try {  val repository = (context.applicationContext as MyApplication).myRepository  data = repository.loadData()  } catch (e: Exception) {  isError = true;  //handleError  }  if (isError) {  ErrorView()  } else {  Content(data)  }  } 

默认错误布局

如果出现未捕获的异常或 Compose 错误,Glance 会显示默认的错误布局:

一条错误消息,其中显示了错误类型以及有关在何处查找错误的建议
图 1. Glance 1.0 默认错误布局
一个显示“无法显示内容”字样的方框
图 2. Glance 1.1.0 默认错误布局

Glance 可让开发者在组合失败时提供 XML 布局作为后备。这意味着 Compose 代码中存在错误。如果应用的代码中存在未捕获的错误,也会显示此错误界面。

class UpgradeWidget : GlanceAppWidget(errorUiLayout = R.layout.error_layout) 

此布局是用户无法与之互动的静态布局,但在紧急情况下非常有用。

包含一个标题和一个用于显示错误消息的文本字段
图 3. 自定义错误布局示例

向默认错误界面添加操作

自 Glance 1.1.0 起,Glance 允许您替换默认的错误处理代码。这样一来,您就可以在组合中发生未捕获的异常或错误时添加操作回调。

如需使用此功能,请替换 onCompositionError() 函数:

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

在此函数中,Glance 会回退到 RemoteViews API 以进行错误处理。这样,您就可以使用 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) } 
  3. 创建一个引用 GlanceAppWidgetReceiver 的待处理 intent:

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

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