توضح هذه الصفحة الممارسات الموصى بها لإنشاء أداة أكثر تقدمًا تجربة مستخدم أفضل.
تحسينات لتحديث محتوى التطبيق المصغّر
قد يكون تحديث محتوى التطبيق المصغّر مُكلفًا من الناحية الحسابية. لتوفير طاقة البطارية تحسين نوع التحديث وتكراره وتوقيته.
أنواع تحديثات التطبيقات المصغّرة
هناك ثلاث طرق لتحديث التطبيق المصغَّر: تحديث كامل، وتحديث جزئي، وهو إعادة تحميل البيانات في حال استخدام أداة جمع. ولكلٍّ من هذه المستويات التكاليف الحاسوبية والتداعيات.
في ما يلي وصف لكل نوع تحديث، كما يوفر مقتطفات رمز لكل نوع.
تحديث كامل: أريد الاتصال بالرقم
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)
. لتحديث التطبيق المصغّر بالكامل. يحل هذا محل البيانات التي تم تقديمها سابقًا.RemoteViews
مع حساب جديدRemoteViews
هذا هو التحديث الأكثر تكلفة من الناحية الحسابية.Kotlin
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)
Java
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)
.Kotlin
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)
Java
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
وفي هذه الأثناء، يتم عرض البيانات القديمة في الأداة. يمكنك لأداء مهام باهظة الثمن بشكل متزامن بهذه الطريقة.Kotlin
val appWidgetManager = AppWidgetManager.getInstance(context) appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
Java
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview);
يمكنك استدعاء هذه الطرق من أي مكان في تطبيقك، طالما أن التطبيق يتضمن
المعرّف الفريد نفسه الخاص بالمعرّف
صف واحد (AppWidgetProvider
).
تحديد عدد مرات تحديث التطبيق المصغّر
يتم تحديث التطبيقات المصغّرة بشكل دوري استنادًا إلى القيمة المقدّمة
updatePeriodMillis
. يمكن تحديث الأداة استجابةً لتفاعل المستخدم أو البث
أو التحديثات أو كليهما.
التحديث بصفة دورية
يمكنك التحكم في تكرار التحديث الدوري من خلال تحديد قيمة
AppWidgetProviderInfo.updatePeriodMillis
في appwidget-provider
XML. على كل
يؤدي هذا التحديث إلى تشغيل طريقة 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 (مستوى واجهة برمجة التطبيقات 24) وAndroid 8.0 (مستوى واجهة برمجة التطبيقات 26)، لا يمكن للتطبيقات تسجيل البيانات الضمنية
عمليات البث في بياناتها، مع بعض
الاستثناءات:
نقاط يجب أخذها في الاعتبار عند تحديث تطبيق مصغّر من جهاز BroadcastRecipient.
إذا تم تحديث التطبيق المصغّر من BroadcastReceiver
، بما في ذلك
AppWidgetProvider
، يُرجى الانتباه إلى الاعتبارات التالية بشأن
مدة وأولوية تحديث التطبيق المصغّر.
مدة التحديث
كقاعدة عامة، يتيح النظام لأجهزة استقبال البث، التي تعمل عادةً في السلسلة الرئيسية، يتم تشغيلها لمدة تصل إلى 10 ثوانٍ قبل اعتبارها غير مستجيبة تشغيل رسالة Application Not جارٍ الاستجابة (ANR). إذا استغرقت وقتًا أطول تحديث الأداة، فيمكنك تجربة البدائل التالية:
جدولة مهمة باستخدام
WorkManager
منح المستلِم المزيد من الوقت من خلال
goAsync
. يتيح ذلك تنفيذ أجهزة الاستقبال لمدة 30 ثانية.
راجع اعتبارات الأمان وأفضل الممارسات الممارسات لمزيد من المعلومات.
أولوية التحديث
تشمل عمليات البث التي يتم إجراؤها باستخدام
AppWidgetProvider.onUpdate
: يتم تشغيلها كعمليات في الخلفية. يعني ذلك
قد تؤدي زيادة تحميل موارد النظام إلى تأخير في استدعاء البث.
المستلم. لمنح الأولوية للبث، اجعله عملية تعمل في المقدّمة.
على سبيل المثال، أضف السمة
Intent.FLAG_RECEIVER_FOREGROUND
وضع علامة على Intent
يتم تمريره إلى PendingIntent.getBroadcast
عندما يمر المستخدم
ينقر على جزء معين من الأداة.
إنشاء معاينات دقيقة تتضمن عناصر ديناميكية
![](https://developer.android.com/static/images/appwidgets/missing-list.png?authuser=9&hl=ar)
يشرح هذا القسم الطريقة الموصى بها لعرض عناصر متعددة في
معاينة أداة بها مجموعة
view - وهو تطبيق مصغّر يستخدم
ListView
أو GridView
أو StackView
وإذا كانت الأداة تستخدم أحد هذه الملفات الشخصية، يمكنك إنشاء معاينة قابلة للتوسع من خلال مباشرة توفير التطبيق المصغّر يؤدي إلى خفض التجربة عندما لا تعرض معاينة الأداة أي عناصر. يحدث هذا بسبب تعيين بيانات عرض المجموعة ديناميكيًا في وقت التشغيل، وتبدو مشابهة الصورة الموضحة في الشكل 1.
لإجراء معاينات للأدوات التي لها طرق عرض مجموعات تظهر بشكل صحيح في التطبيق المصغَّر
ننصح بالاحتفاظ بملف تخطيط منفصل مخصص
معاينة. يتضمن ملف التخطيط المنفصل هذا تخطيط الأداة الفعلي
عرض مجموعة العناصر النائبة بالعناصر المزيفة على سبيل المثال، يمكنك تقليد
ListView
من خلال توفير العنصر النائب LinearLayout
الذي يتضمّن عدة قوائم مزيفة
عناصر.
لتوضيح مثال لـ 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>