توضح هذه الصفحة الممارسات الموصى بها لإنشاء أداة أكثر تقدمًا تجربة مستخدم أفضل.
تحسينات لتحديث محتوى التطبيق المصغّر
قد يكون تحديث محتوى التطبيق المصغّر مُكلفًا من الناحية الحسابية. لتوفير شحن البطارية، عليك تحسين نوع التحديث ومعدّل تكراره وتوقيته.
أنواع تحديثات التطبيقات المصغّرة
هناك ثلاث طرق لتحديث التطبيق المصغَّر: تحديث كامل، وتحديث جزئي، وهو إعادة تحميل البيانات في حال استخدام أداة جمع. ولكلٍّ من هذه المستويات التكاليف الحاسوبية والتداعيات.
يوضّح ما يلي كل نوع من أنواع التعديلات ويقدّم مقتطفات رمز لكل منها.
تحديث كامل: أريد الاتصال بالرقم
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
في ملف 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 (مستوى واجهة برمجة التطبيقات 24) وAndroid 8.0 (مستوى واجهة برمجة التطبيقات 26)، لا يمكن للتطبيقات تسجيل البيانات الضمنية
عمليات البث في بياناتها، مع بعض
الاستثناءات:
نقاط يجب أخذها في الاعتبار عند تحديث تطبيق مصغّر من جهاز BroadcastRecipient.
إذا تم تحديث التطبيق المصغّر من BroadcastReceiver
، بما في ذلك
AppWidgetProvider
، يُرجى الانتباه إلى الاعتبارات التالية بشأن
مدة وأولوية تحديث التطبيق المصغّر.
مدة التحديث
كقاعدة عامة، يتيح النظام لأجهزة استقبال البث، التي تعمل عادةً في السلسلة الرئيسية، يتم تشغيلها لمدة تصل إلى 10 ثوانٍ قبل اعتبارها غير مستجيبة تشغيل رسالة Application Not جارٍ الاستجابة (ANR). إذا استغرقت عملية تعديل التطبيق المصغّر وقتًا أطول، ننصحك باتّباع الخطوات التالية:
حدِّد موعدًا لمهمة باستخدام
WorkManager
.منح المستلِم المزيد من الوقت من خلال
goAsync
. يتيح ذلك للمستلمين تنفيذ الإجراء لمدة 30 ثانية.
راجع اعتبارات الأمان وأفضل الممارسات الممارسات لمزيد من المعلومات.
أولوية التحديث
تشمل عمليات البث التي يتم إجراؤها باستخدام
AppWidgetProvider.onUpdate
: يتم تشغيلها كعمليات في الخلفية. يعني ذلك
قد تؤدي زيادة تحميل موارد النظام إلى تأخير في استدعاء البث.
المستلم. لمنح الأولوية للبث، اجعله عملية تعمل في المقدّمة.
على سبيل المثال، أضف السمة
Intent.FLAG_RECEIVER_FOREGROUND
وضع علامة على Intent
يتم تمريره إلى PendingIntent.getBroadcast
عندما يمر المستخدم
ينقر على جزء معين من الأداة.
إنشاء معاينات دقيقة تتضمّن عناصر ديناميكية
يشرح هذا القسم الطريقة الموصى بها لعرض عناصر متعددة في
معاينة أداة بها مجموعة
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>