این صفحه روش های توصیه شده برای ایجاد یک ویجت پیشرفته تر برای تجربه کاربری بهتر را توضیح می دهد.
بهینه سازی برای به روز رسانی محتوای ویجت
به روز رسانی محتوای ویجت می تواند از نظر محاسباتی گران باشد. برای صرفه جویی در مصرف باتری، نوع به روز رسانی، فرکانس و زمان بندی را بهینه کنید.
انواع به روز رسانی ویجت
سه راه برای به روز رسانی یک ویجت وجود دارد: به روز رسانی کامل، به روز رسانی جزئی، و در مورد ویجت مجموعه، به روز رسانی داده ها. هر کدام هزینه های محاسباتی و پیامدهای متفاوتی دارند.
موارد زیر هر نوع به روز رسانی را توضیح می دهد و کدهایی را برای هر کدام ارائه می دهد.
به روز رسانی کامل: برای به روز رسانی کامل ویجت، با
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)
تماس بگیرید. اینRemoteViews
ارائه شده قبلی را باRemoteViews
جدید جایگزین می کند. این گران ترین به روز رسانی محاسباتی است.کاتلین
val appWidgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also { setTextViewText(R.id.textview_widget_layout1, "Updated text1") setTextViewText(R.id.textview_widget_layout2, "Updated text2") } appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
جاوا
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout); remoteViews.setTextViewText(R.id.textview_widget_layout1, "Updated text1"); remoteViews.setTextViewText(R.id.textview_widget_layout2, "Updated text2"); appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
به روز رسانی جزئی: برای به روز رسانی بخش هایی از ویجت با
AppWidgetManager.partiallyUpdateAppWidget
تماس بگیرید. اینRemoteViews
جدید را باRemoteViews
ارائه شده قبلی ادغام می کند. اگر ویجت حداقل یک بهروزرسانی کامل را از طریقupdateAppWidget(int[], RemoteViews)
دریافت نکند، این روش نادیده گرفته میشود.کاتلین
val appWidgetManager = AppWidgetManager.getInstance(context) val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also { setTextViewText(R.id.textview_widget_layout, "Updated text") } appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)
جاوا
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout); remoteViews.setTextViewText(R.id.textview_widget_layout, "Updated text"); appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews);
بازخوانی دادههای مجموعه: با
AppWidgetManager.notifyAppWidgetViewDataChanged
تماس بگیرید تا دادههای نمای مجموعه در ویجت خود را باطل کنید. این باعث می شودRemoteViewsFactory.onDataSetChanged
. در این میان، داده های قدیمی در ویجت نمایش داده می شوند. با این روش می توانید با خیال راحت کارهای گران قیمت را به صورت همزمان انجام دهید.کاتلین
val appWidgetManager = AppWidgetManager.getInstance(context) appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
جاوا
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview);
تا زمانی که برنامه دارای همان 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
انتخاب کنید.
به روز رسانی در پاسخ به یک رویداد پخش
نمونه ای از یک رویداد پخش که برای به روز رسانی به ویجت نیاز دارد، زمانی است که کاربر عکس می گیرد. در این حالت، شما می خواهید وقتی یک عکس جدید شناسایی شد، ویجت را به روز کنید.
میتوانید یک کار را با JobScheduler
زمانبندی کنید و با استفاده از روش JobInfo.Builder.addTriggerContentUri
پخش را به عنوان محرک مشخص کنید.
همچنین میتوانید یک BroadcastReceiver
برای پخش ثبت کنید - برای مثال، گوش دادن به ACTION_LOCALE_CHANGED
. با این حال، چون این کار منابع دستگاه را مصرف می کند، با احتیاط از آن استفاده کنید و فقط به پخش خاص گوش دهید. با معرفی محدودیتهای پخش در Android 7.0 (سطح API 24) و Android 8.0 (سطح API 26)، برنامهها نمیتوانند پخشهای ضمنی را در مانیفستهای خود ثبت کنند، به استثنای برخی موارد .
ملاحظات هنگام به روز رسانی یک ویجت از یک BroadcastReceiver
اگر ویجت از یک BroadcastReceiver
، از جمله AppWidgetProvider
بهروزرسانی میشود، از ملاحظات زیر در رابطه با مدت زمان و اولویت بهروزرسانی ویجت آگاه باشید.
مدت زمان به روز رسانی
به عنوان یک قاعده، سیستم به گیرندههای پخش که معمولاً در رشته اصلی برنامه اجرا میشوند، اجازه میدهد تا 10 ثانیه قبل از اینکه آنها را پاسخگو نمیداند و خطای Application Not Responding (ANR) را راهاندازی کند، کار کنند. اگر بهروزرسانی ویجت بیشتر طول میکشد، گزینههای زیر را در نظر بگیرید:
با استفاده از
WorkManager
یک کار را برنامه ریزی کنید.با روش
goAsync
به گیرنده زمان بیشتری بدهید. این به گیرنده ها اجازه می دهد تا 30 ثانیه اجرا شوند.
برای اطلاعات بیشتر به ملاحظات امنیتی و بهترین شیوه ها مراجعه کنید.
اولویت به روز رسانی
به طور پیشفرض، پخشها - از جمله آنهایی که با استفاده از AppWidgetProvider.onUpdate
ساخته شدهاند - به عنوان فرآیندهای پسزمینه اجرا میشوند. این بدان معناست که منابع بیش از حد سیستم می تواند باعث تاخیر در فراخوانی گیرنده پخش شود. برای اولویت بندی پخش، آن را به یک فرآیند پیش زمینه تبدیل کنید.
برای مثال، پرچم Intent.FLAG_RECEIVER_FOREGROUND
را به Intent
اضافه کنید که به PendingIntent.getBroadcast
زمانی که کاربر روی قسمت خاصی از ویجت ضربه میزند.
پیش نمایش های دقیقی بسازید که شامل موارد پویا باشد
این بخش روش توصیه شده برای نمایش چندین مورد در یک پیشنمایش ویجت را برای یک ویجت با نمای مجموعه توضیح میدهد - یعنی ویجتی که از ListView
، GridView
یا StackView
استفاده میکند.
اگر ویجت شما از یکی از این نماها استفاده میکند، ایجاد یک پیشنمایش مقیاسپذیر با ارائه مستقیم طرحبندی واقعی ویجت، زمانی که پیشنمایش ویجت هیچ موردی را نمایش نمیدهد، تجربه را کاهش میدهد. این به این دلیل رخ می دهد که داده های نمای مجموعه به صورت پویا در زمان اجرا تنظیم می شوند و شبیه تصویر نشان داده شده در شکل 1 به نظر می رسد.
برای اینکه پیشنمایش ویجتها با نمای مجموعه به درستی در انتخابگر ویجت نمایش داده شوند، توصیه میکنیم یک فایل طرحبندی جداگانه که فقط برای پیشنمایش تعیین شده است نگهداری کنید. این فایل طرحبندی جداگانه شامل طرحبندی ویجت واقعی و نمای مجموعه مکاننما با موارد جعلی است. به عنوان مثال، میتوانید با ارائه یک مکان نگهدار LinearLayout
با چندین آیتم فهرست جعلی، ListView
تقلید کنید.
برای نشان دادن مثالی برای ListView
، با یک فایل طرح بندی جداگانه شروع کنید:
// res/layout/widget_preview.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/widget_background"
android:orientation="vertical">
// Include the actual widget layout that contains ListView.
<include
layout="@layout/widget_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
// The number of fake items you include depends on the values you provide
// for minHeight or targetCellHeight in the AppWidgetProviderInfo
// definition.
<TextView android:text="@string/fake_item1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="?attr/appWidgetInternalPadding" />
<TextView android:text="@string/fake_item2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="?attr/appWidgetInternalPadding" />
</LinearLayout>
هنگام ارائه ویژگی previewLayout
فراداده AppWidgetProviderInfo
، فایل طرح بندی پیش نمایش را مشخص کنید. شما همچنان طرح بندی واقعی ویجت را برای ویژگی initialLayout
مشخص می کنید و هنگام ساخت RemoteViews
در زمان اجرا از طرح بندی واقعی ویجت استفاده می کنید.
<appwidget-provider
previewLayout="@layout/widget_previe"
initialLayout="@layout/widget_view" />
موارد لیست پیچیده
مثال در بخش قبل موارد جعلی لیست را ارائه می دهد، زیرا موارد لیست، اشیاء TextView
هستند. اگر اقلام دارای طرحبندی پیچیده باشند، ارائه اقلام جعلی میتواند پیچیدهتر باشد.
یک آیتم لیست را در نظر بگیرید که در widget_list_item.xml
تعریف شده است و از دو شی TextView
تشکیل شده است:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:id="@id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/fake_title" />
<TextView android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/fake_content" />
</LinearLayout>
برای ارائه آیتمهای فهرست جعلی، میتوانید طرحبندی را چندین بار اضافه کنید، اما این باعث میشود هر آیتم فهرست یکسان باشد. برای ارائه اقلام لیست منحصر به فرد، این مراحل را دنبال کنید:
مجموعه ای از ویژگی ها را برای مقادیر متن ایجاد کنید:
<resources> <attr name="widgetTitle" format="string" /> <attr name="widgetContent" format="string" /> </resources>
برای تنظیم متن از این ویژگی ها استفاده کنید:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="?widgetTitle" /> <TextView android:id="@id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="?widgetContent" /> </LinearLayout>
هر تعداد سبک که برای پیش نمایش لازم است ایجاد کنید. مقادیر را در هر سبک دوباره تعریف کنید:
<resources> <style name="Theme.Widget.ListItem"> <item name="widgetTitle"></item> <item name="widgetContent"></item> </style> <style name="Theme.Widget.ListItem.Preview1"> <item name="widgetTitle">Fake Title 1</item> <item name="widgetContent">Fake content 1</item> </style> <style name="Theme.Widget.ListItem.Preview2"> <item name="widgetTitle">Fake title 2</item> <item name="widgetContent">Fake content 2</item> </style> </resources>
استایلها را روی موارد جعلی در طرحبندی پیشنمایش اعمال کنید:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" ...> <include layout="@layout/widget_view" ... /> <include layout="@layout/widget_list_item" android:theme="@style/Theme.Widget.ListItem.Preview1" /> <include layout="@layout/widget_list_item" android:theme="@style/Theme.Widget.ListItem.Preview2" /> </LinearLayout>