[null,null,["最后更新时间 (UTC):2025-08-21。"],[],[],null,["# Create an advanced widget\n\nTry the Compose way \nJetpack Compose is the recommended UI toolkit for Android. Learn how to build widgets using Compose-style APIs. \n[Jetpack Glance →](/develop/ui/compose/glance) \n\n\u003cbr /\u003e\n\nThis page explains recommended practices for creating a more advanced widget for\na better user experience.\n\nOptimizations for updating widget content\n-----------------------------------------\n\nUpdating widget content can be computationally expensive. To save battery\nconsumption, optimize the update type, frequency, and timing.\n\n### Types of widget updates\n\nThere are three ways to update a widget: a full update, a partial update, and,\nin the case of a collection widget, a data refresh. Each has different\ncomputational costs and ramifications.\n\nThe following describes each update type and provides code snippets for each.\n\n- **Full update:** call [`AppWidgetManager.updateAppWidget(int,\n android.widget.RemoteViews)`](/reference/android/appwidget/AppWidgetManager#updateAppWidget(int,%20android.widget.RemoteViews))\n to fully update the widget. This replaces the previously provided\n [`RemoteViews`](/reference/android/widget/RemoteViews) with a new\n `RemoteViews`. This is the most computationally expensive update.\n\n ### Kotlin\n\n ```kotlin\n val appWidgetManager = AppWidgetManager.getInstance(context)\n val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also {\n setTextViewText(R.id.textview_widget_layout1, \"Updated text1\")\n setTextViewText(R.id.textview_widget_layout2, \"Updated text2\")\n }\n appWidgetManager.updateAppWidget(appWidgetId, remoteViews)\n ```\n\n ### Java\n\n ```java\n AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);\n RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);\n remoteViews.setTextViewText(R.id.textview_widget_layout1, \"Updated text1\");\n remoteViews.setTextViewText(R.id.textview_widget_layout2, \"Updated text2\");\n appWidgetManager.updateAppWidget(appWidgetId, remoteViews);\n ```\n- **Partial update:** call\n [`AppWidgetManager.partiallyUpdateAppWidget`](/reference/android/appwidget/AppWidgetManager#partiallyUpdateAppWidget(int,%20android.widget.RemoteViews))\n to update parts of the widget. This merges the new `RemoteViews` with the\n previously provided `RemoteViews`. This method is ignored if a widget\n doesn't receive at least one full update through [`updateAppWidget(int[],\n RemoteViews)`](/reference/android/appwidget/AppWidgetManager#updateAppWidget(android.content.ComponentName,%20android.widget.RemoteViews)).\n\n ### Kotlin\n\n ```kotlin\n val appWidgetManager = AppWidgetManager.getInstance(context)\n val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also {\n setTextViewText(R.id.textview_widget_layout, \"Updated text\")\n }\n appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)\n ```\n\n ### Java\n\n ```java\n AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);\n RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);\n remoteViews.setTextViewText(R.id.textview_widget_layout, \"Updated text\");\n appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews);\n ```\n- **Collection data refresh:** call\n [`AppWidgetManager.notifyAppWidgetViewDataChanged`](/reference/android/appwidget/AppWidgetManager#notifyAppWidgetViewDataChanged(int,%20int))\n to invalidate the data of a collection view in your widget. This triggers\n [`RemoteViewsFactory.onDataSetChanged`](/reference/android/widget/RemoteViewsService.RemoteViewsFactory#onDataSetChanged()).\n In the interim, the old data is displayed in the widget. You can safely\n perform expensive tasks synchronously with this method.\n\n ### Kotlin\n\n ```kotlin\n val appWidgetManager = AppWidgetManager.getInstance(context)\n appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)\n ```\n\n ### Java\n\n ```java\n AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);\n appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview);\n ```\n\nYou can call these methods from anywhere in your app, as long as the app has the\nsame UID as the corresponding\n[`AppWidgetProvider`](/reference/android/appwidget/AppWidgetProvider) class.\n\n### Determine how often to update a widget\n\nWidgets are updated periodically depending on the value provided for the\n[`updatePeriodMillis`](/reference/android/appwidget/AppWidgetProviderInfo#updatePeriodMillis)\nattribute. The widget can update in response to user interaction, broadcast\nupdates, or both.\n\n#### Update periodically\n\nYou can control the frequency of the periodic update by specifying a value for\n`AppWidgetProviderInfo.updatePeriodMillis` in the `appwidget-provider` XML. Each\nupdate triggers the `AppWidgetProvider.onUpdate()` method, which is where you\ncan place the code to update the widget. However, consider the [alternatives for\nbroadcast receiver updates](#broadcastreceiver-duration) described in a\nfollowing section if your widget needs to load data asynchronously or takes more\nthan 10 seconds to update, because after 10 seconds, the system considers a\n`BroadcastReceiver` to be non-responsive.\n\n`updatePeriodMillis` doesn't support values of less than 30 minutes. However, if\nyou want to disable periodic updates, you can specify 0.\n\nYou can let users adjust the frequency of updates in a configuration. For\nexample, they might want a stock ticker to update every 15 minutes or only four\ntimes a day. In this case, set the `updatePeriodMillis` to 0 and use\n[`WorkManager`](/topic/libraries/architecture/workmanager) instead.\n| **Note:** Using repeating tasks with `WorkManager` is a good option, but similar power restrictions apply. See [App Standby\n| Buckets](/about/versions/pie/power#buckets) for more information.\n\n#### Update in response to a user interaction\n\nHere are some recommended ways to update the widget based on user interaction:\n\n- **From an activity of the app:** directly call\n `AppWidgetManager.updateAppWidget` in response to a user interaction, such\n as a user's tap.\n\n- **From remote interactions, such as a notification or an app widget:**\n construct a `PendingIntent`, then update the widget from the invoked\n `Activity`, `Broadcast`, or `Service`. You can choose your own priority. For\n example, if you select a `Broadcast` for the `PendingIntent`, you can choose\n a [foreground broadcast](#broadcastreceiver-priority) to give the\n `BroadcastReceiver` priority.\n\n#### Update in response to a broadcast event\n\nAn example of a broadcast event that requires a widget to update is when the\nuser takes a photo. In this case, you want to update the widget when a new photo\nis detected.\n\nYou can schedule a job with `JobScheduler` and specify a broadcast as the\ntrigger using the\n[`JobInfo.Builder.addTriggerContentUri`](/reference/android/app/job/JobInfo.Builder#addTriggerContentUri(android.app.job.JobInfo.TriggerContentUri))\nmethod.\n\nYou can also register a `BroadcastReceiver` for the broadcast---for example,\nlistening for\n[`ACTION_LOCALE_CHANGED`](/reference/android/content/Intent#ACTION_LOCALE_CHANGED).\nHowever, because this consumes device resources, use this with care and listen\nonly to the specific broadcast. With the introduction of [broadcast\nlimitations](/about/versions/oreo/background#broadcasts) in Android\n7.0 (API level 24) and Android 8.0 (API level 26), apps can't register implicit\nbroadcasts in their manifests, with certain\n[exceptions](/guide/components/broadcast-exceptions).\n\n### Considerations when updating a widget from a BroadcastReceiver\n\nIf the widget is updated from a `BroadcastReceiver`, including\n`AppWidgetProvider`, be aware of the following considerations regarding the\nduration and priority of a widget update.\n\n#### Duration of the update\n\nAs a rule, the system lets broadcast receivers, which usually run in the app's\nmain thread, run for up to 10 seconds before considering them non-responsive and\ntriggering an [Application Not\nResponding](/topic/performance/vitals/anr) (ANR) error. To avoid blocking the\nmain thread while handling the broadcast, use the\n[`goAsync`](/reference/android/content/BroadcastReceiver#goAsync()) method. If it takes\nlonger to update the widget, consider scheduling a task\nusing [`WorkManager`](/reference/androidx/work/WorkManager). \n\n Caution: Any work you do here blocks further broadcasts until it completes,\n so it can slow the receiving of later events.\n\nSee [Security considerations and best\npractices](/guide/components/broadcasts#security-and-best-practices) for more\ninformation.\n\n#### Priority of the update\n\nBy default, broadcasts---including those made using\n`AppWidgetProvider.onUpdate`---run as background processes. This means\noverloaded system resources can cause a delay in the invocation of the broadcast\nreceiver. To prioritize the broadcast, make it a foreground process.\n\nFor example, add the\n[`Intent.FLAG_RECEIVER_FOREGROUND`](/reference/android/content/Intent#FLAG_RECEIVER_FOREGROUND)\nflag to the `Intent` passed to the `PendingIntent.getBroadcast` when the user\ntaps on a certain part of the widget."]]