این صفحه روش های توصیه شده برای ایجاد یک ویجت پیشرفته تر برای تجربه کاربری بهتر را توضیح می دهد.
بهینه سازی برای به روز رسانی محتوای ویجت
به روز رسانی محتوای ویجت می تواند از نظر محاسباتی گران باشد. برای صرفه جویی در مصرف باتری، نوع به روز رسانی، فرکانس و زمان بندی را بهینه کنید.
انواع به روز رسانی ویجت
سه راه برای به روز رسانی یک ویجت وجود دارد: به روز رسانی کامل، به روز رسانی جزئی، و در مورد ویجت مجموعه، به روز رسانی داده ها. هر کدام هزینه های محاسباتی و پیامدهای متفاوتی دارند.
موارد زیر هر نوع به روز رسانی را توضیح می دهد و کدهایی را برای هر کدام ارائه می دهد.
بازخوانی دادههای مجموعه: با AppWidgetManager.notifyAppWidgetViewDataChanged تماس بگیرید تا دادههای نمای مجموعه در ویجت خود را باطل کنید. این باعث می شود RemoteViewsFactory.onDataSetChanged . در این میان، داده های قدیمی در ویجت نمایش داده می شوند. با این روش می توانید با خیال راحت کارهای گران قیمت را به صورت همزمان انجام دهید.
تا زمانی که برنامه دارای همان UID کلاس AppWidgetProvider مربوطه باشد، میتوانید این روشها را از هر کجای برنامه خود فراخوانی کنید.
تعیین کنید هر چند وقت یکبار یک ویجت را به روز کنید
ویجت ها به صورت دوره ای بسته به مقدار ارائه شده برای ویژگی updatePeriodMillis به روز می شوند. ویجت میتواند در پاسخ به تعامل کاربر، بهروزرسانیهای پخش یا هر دو بهروزرسانی شود.
به صورت دوره ای به روز کنید
میتوانید با تعیین یک مقدار برای AppWidgetProviderInfo.updatePeriodMillis در XML appwidget-provider فرکانس بهروزرسانی دورهای را کنترل کنید. هر به روز رسانی متد AppWidgetProvider.onUpdate() فعال می کند، جایی که می توانید کد را برای به روز رسانی ویجت قرار دهید. با این حال، اگر ویجت شما نیاز به بارگیری داده ها به صورت ناهمزمان یا بیش از 10 ثانیه طول می کشد تا به روز رسانی شود، گزینه های جایگزین برای به روز رسانی گیرنده پخش که در بخش زیر توضیح داده شده است را در نظر بگیرید، زیرا پس از 10 ثانیه، سیستم یک BroadcastReceiver را پاسخگو نمی داند.
updatePeriodMillis از مقادیر کمتر از 30 دقیقه پشتیبانی نمی کند. با این حال، اگر می خواهید به روز رسانی های دوره ای را غیرفعال کنید، می توانید 0 را تعیین کنید.
میتوانید به کاربران اجازه دهید فرکانس بهروزرسانیها را در یک پیکربندی تنظیم کنند. به عنوان مثال، آنها ممکن است بخواهند که یک علامت سهام هر 15 دقیقه یا فقط چهار بار در روز به روز شود. در این حالت، updatePeriodMillis روی 0 قرار دهید و به جای آن از WorkManager استفاده کنید.
به روز رسانی در پاسخ به تعامل کاربر
در اینجا چند روش توصیه شده برای به روز رسانی ویجت بر اساس تعامل کاربر آورده شده است:
از یک فعالیت برنامه: مستقیماً با AppWidgetManager.updateAppWidget در پاسخ به تعامل کاربر، مانند ضربه زدن کاربر، تماس بگیرید.
از تعاملات راه دور، مانند اعلان یا ویجت برنامه: یک PendingIntent بسازید، سپس ویجت را از Activity ، Broadcast یا Service فراخوانی شده به روز کنید. شما می توانید اولویت خود را انتخاب کنید. به عنوان مثال، اگر یک Broadcast برای PendingIntent انتخاب کنید، می توانید یک پخش پیش زمینه را برای اولویت دادن BroadcastReceiver انتخاب کنید.
به روز رسانی در پاسخ به یک رویداد پخش
نمونه ای از یک رویداد پخش که برای به روز رسانی به ویجت نیاز دارد، زمانی است که کاربر عکس می گیرد. در این حالت، شما می خواهید وقتی یک عکس جدید شناسایی شد، ویجت را به روز کنید.
همچنین میتوانید یک BroadcastReceiver برای پخش ثبت کنید - برای مثال، گوش دادن به ACTION_LOCALE_CHANGED . با این حال، چون این کار منابع دستگاه را مصرف می کند، با احتیاط از آن استفاده کنید و فقط به پخش خاص گوش دهید. با معرفی محدودیتهای پخش در Android 7.0 (سطح API 24) و Android 8.0 (سطح API 26)، برنامهها نمیتوانند پخشهای ضمنی را در مانیفستهای خود ثبت کنند، به استثنای برخی موارد .
ملاحظات هنگام به روز رسانی یک ویجت از یک BroadcastReceiver
اگر ویجت از یک BroadcastReceiver ، از جمله AppWidgetProvider بهروزرسانی میشود، از ملاحظات زیر در رابطه با مدت زمان و اولویت بهروزرسانی ویجت آگاه باشید.
مدت زمان به روز رسانی
به عنوان یک قاعده، سیستم به گیرندههای پخش که معمولاً در رشته اصلی برنامه اجرا میشوند، اجازه میدهد تا 10 ثانیه قبل از اینکه آنها را پاسخگو نمیداند و خطای Application Not Responding (ANR) را راهاندازی کند، کار کنند. برای جلوگیری از مسدود شدن رشته اصلی در هنگام مدیریت پخش، از روش goAsync استفاده کنید. اگر بهروزرسانی ویجت بیشتر طول میکشد، با استفاده از WorkManager یک کار را زمانبندی کنید.
به طور پیشفرض، پخشها - از جمله آنهایی که با استفاده از AppWidgetProvider.onUpdate ساخته شدهاند - به عنوان فرآیندهای پسزمینه اجرا میشوند. این بدان معناست که منابع بیش از حد سیستم می تواند باعث تاخیر در فراخوانی گیرنده پخش شود. برای اولویت بندی پخش، آن را به یک فرآیند پیش زمینه تبدیل کنید.
برای مثال، پرچم Intent.FLAG_RECEIVER_FOREGROUND را به Intent اضافه کنید که به PendingIntent.getBroadcast زمانی که کاربر روی قسمت خاصی از ویجت ضربه میزند.
محتوا و نمونه کدها در این صفحه مشمول پروانههای توصیفشده در پروانه محتوا هستند. جاوا و OpenJDK علامتهای تجاری یا علامتهای تجاری ثبتشده Oracle و/یا وابستههای آن هستند.
تاریخ آخرین بهروزرسانی 2025-08-27 بهوقت ساعت هماهنگ جهانی.
[[["درک آسان","easyToUnderstand","thumb-up"],["مشکلم را برطرف کرد","solvedMyProblem","thumb-up"],["غیره","otherUp","thumb-up"]],[["اطلاعاتی که نیاز دارم وجود ندارد","missingTheInformationINeed","thumb-down"],["بیشازحد پیچیده/ مراحل بسیار زیاد","tooComplicatedTooManySteps","thumb-down"],["قدیمی","outOfDate","thumb-down"],["مشکل ترجمه","translationIssue","thumb-down"],["مشکل کد / نمونهها","samplesCodeIssue","thumb-down"],["غیره","otherDown","thumb-down"]],["تاریخ آخرین بهروزرسانی 2025-08-27 بهوقت ساعت هماهنگ جهانی."],[],[],null,["Try 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\nUpdating widget content can be computationally expensive. To save battery\nconsumption, optimize the update type, frequency, and timing.\n\nTypes 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\nDetermine 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\nUpdate 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\nUpdate 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\nUpdate 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\nConsiderations 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\nDuration 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\nPriority 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."]]