ऐडवांस विजेट बनाएं

इस पेज में बताया गया है कि आप विजेट को बेहतर बनाने के लिए किन तरीकों का इस्तेमाल करना चाहते हैं बेहतर उपयोगकर्ता अनुभव मिलता है.

विजेट का कॉन्टेंट अपडेट करने के लिए ऑप्टिमाइज़ेशन

विजेट का कॉन्टेंट अपडेट करने के लिए, ज़्यादा कंप्यूटिंग की ज़रूरत पड़ सकती है. बैटरी बचाने के लिए इस्तेमाल करना, अपडेट टाइप, फ़्रीक्वेंसी, और समय को ऑप्टिमाइज़ करना.

विजेट के अपडेट के टाइप

विजेट को अपडेट करने के तीन तरीके हैं: पूरा अपडेट, कुछ हिस्से का अपडेट, और कलेक्शन विजेट के मामले में, डेटा रीफ़्रेश करना. हर स्थिति अलग होती है लागत और जटिलताओं के बारे में बताएं.

यहां हर तरह के अपडेट के बारे में बताया गया है. साथ ही, हर अपडेट के लिए कोड स्निपेट भी दिए गए हैं.

  • पूरा अपडेट: 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 एट्रिब्यूट की वैल्यू सबमिट करें. उपयोगकर्ता इंटरैक्शन के जवाब में विजेट अपडेट हो सकता है, ब्रॉडकास्ट अपडेट या फिर दोनों का इस्तेमाल करें.

समय-समय पर अपडेट करें

आप समय-समय पर होने वाले अपडेट की फ़्रीक्वेंसी को appwidget-provider एक्सएमएल में AppWidgetProviderInfo.updatePeriodMillis. हर अपडेट, AppWidgetProvider.onUpdate() तरीके को ट्रिगर करता है. यहां विजेट को अपडेट करने के लिए कोड डाला जा सकता है. हालांकि, के लिए विकल्पों ब्रॉडकास्ट रिसीवर में बताए गए अपडेट यदि विजेट को एसिंक्रोनस रूप से डेटा लोड करने की आवश्यकता है या 10 सेकंड से कम समय में अपडेट होता है, क्योंकि 10 सेकंड के बाद, सिस्टम जवाब न देने के लिए BroadcastReceiver.

updatePeriodMillis में, 30 मिनट से कम की वैल्यू इस्तेमाल नहीं की जा सकतीं. हालांकि, अगर आपको समय-समय पर होने वाले अपडेट बंद करने हैं, तो 0 डालें.

उपयोगकर्ताओं को कॉन्फ़िगरेशन में, अपडेट की फ़्रीक्वेंसी में बदलाव करने की अनुमति दी जा सकती है. इसके लिए उदाहरण के लिए, हो सकता है कि वे स्टॉक टिकर को हर 15 मिनट या सिर्फ़ चार बार अपडेट करना चाहें दिन में कई बार. इस मामले में, updatePeriodMillis को 0 पर सेट करें और इसके बजाय, WorkManager का इस्तेमाल करें.

उपयोगकर्ता के इंटरैक्शन के जवाब में अपडेट करना

लोगों के इंटरैक्शन के आधार पर, विजेट को अपडेट करने के कुछ तरीके यहां सुझाए गए हैं:

  • ऐप्लिकेशन की किसी गतिविधि से: सीधे कॉल करें उपयोगकर्ता इंटरैक्शन के जवाब में AppWidgetManager.updateAppWidget, जैसे टैप किया जा सकता है.

  • रिमोट इंटरैक्शन, जैसे कि सूचना या ऐप्लिकेशन के विजेट से: PendingIntent बनाएं. इसके बाद, लागू किए गए विजेट में से विजेट को अपडेट करें Activity, Broadcast या Service. आपके पास अपनी प्राथमिकता चुनने का विकल्प होता है. इसके लिए उदाहरण के लिए, अगर PendingIntent के लिए Broadcast चुना जाता है, तो एक फ़ोरग्राउंड ब्रॉडकास्ट BroadcastReceiver प्राथमिकता.

ब्रॉडकास्ट इवेंट के जवाब में अपडेट करें

जब कोई उपयोगकर्ता फ़ोटो लेता है, तो उसे ब्रॉडकास्ट इवेंट के तौर पर सेट किया जा सकता है. इस इवेंट के होने पर, विजेट को अपडेट करना ज़रूरी होता है. इस मामले में, आपको नई फ़ोटो का पता चलने पर विजेट अपडेट करना है.

JobScheduler का इस्तेमाल करके कोई जॉब शेड्यूल किया जा सकता है. साथ ही, JobInfo.Builder.addTriggerContentUri तरीके का इस्तेमाल करके, ट्रिगर के तौर पर ब्रॉडकास्ट तय किया जा सकता है.

ब्रॉडकास्ट के लिए भी BroadcastReceiver रजिस्टर किया जा सकता है. उदाहरण के लिए, ACTION_LOCALE_CHANGED सुनने के लिए. हालांकि, इसमें डिवाइस के संसाधनों का इस्तेमाल होता है. इसलिए, इसका इस्तेमाल सावधानी से करें और ध्यान से सुनें सिर्फ़ खास ब्रॉडकास्ट पर. Android 7.0 (एपीआई लेवल 24) और Android 8.0 (एपीआई लेवल 26) में ब्रॉडकास्ट से जुड़ी पाबंदियां लागू होने के बाद, ऐप्लिकेशन अपने मेनिफ़ेस्ट में, कुछ अपवादों के साथ, इंप्लिसिट ब्रॉडकास्ट रजिस्टर नहीं कर सकते.

BroadcastReceiver से विजेट अपडेट करते समय ध्यान रखने वाली बातें

अगर विजेट को BroadcastReceiver से अपडेट किया जाता है, तो इसमें ये भी शामिल हैं AppWidgetProvider को ध्यान रखें. इन बातों का ध्यान रखें: विजेट के अपडेट होने की अवधि और प्राथमिकता.

अपडेट होने में लगने वाला समय

नियम के तौर पर, सिस्टम ब्रॉडकास्ट रिसीवर की अनुमति देता है, जो आम तौर पर ऐप्लिकेशन के मुख्य थ्रेड को 10 सेकंड तक चलाया जा सकता है. इसके बाद ही, ये थ्रेड किसी भी तरह से जवाब दिए जा सकेंगे और ऐप्लिकेशन नहीं है जवाब देने से जुड़ी (ANR) गड़बड़ी. अगर सेटलमेंट में ज़्यादा समय लगता है, विजेट को अपडेट करने के लिए, नीचे दिए गए विकल्प आज़माएं:

  • WorkManager का इस्तेमाल करके कोई टास्क शेड्यूल करें.

  • goAsync तरीके का इस्तेमाल करके, ईमेल पाने वाले व्यक्ति को ज़्यादा समय दें. इससे रिसीवर 30 सेकंड तक काम करता है.

सुरक्षा से जुड़ी खास बातें और सबसे सही सुझाव देखें तरीके जानकारी.

अपडेट की प्राथमिकता

डिफ़ॉल्ट रूप से, ब्रॉडकास्ट AppWidgetProvider.onUpdate—बैकग्राउंड प्रोसेस के तौर पर चलता है. इसका मतलब है कि सिस्टम के संसाधनों के ज़्यादा इस्तेमाल की वजह से, ब्रॉडकास्ट रिसीवर को शुरू करने में देरी हो सकती है. ब्रॉडकास्ट को प्राथमिकता देने के लिए, उसे फ़ोरग्राउंड प्रोसेस बनाएं.

उदाहरण के लिए, जब उपयोगकर्ता विजेट के किसी हिस्से पर टैप करता है, तो PendingIntent.getBroadcast को पास किए गए Intent में Intent.FLAG_RECEIVER_FOREGROUND फ़्लैग जोड़ें.

डाइनैमिक आइटम शामिल करके, सटीक झलकें बनाना

पहली इमेज: विजेट की झलक, जिसमें सूची में कोई आइटम नहीं दिख रहा है.

यह सेक्शन कलेक्शन वाले विजेट के विजेट की झलक देखें—यानी कि एक ऐसा विजेट जो ListView, GridView या StackView.

अगर आपका विजेट इनमें से किसी एक व्यू का इस्तेमाल करता है, तो विजेट का असल लेआउट देकर स्केलेबल झलक बनाने पर, विजेट की झलक में कोई आइटम न दिखने पर, विजेट का इस्तेमाल करने का अनुभव खराब हो जाता है. ऐसा इसलिए होता है, क्योंकि कलेक्शन व्यू का डेटा रनटाइम के दौरान डाइनैमिक तौर पर सेट होता है. यह पहली इमेज में दिखाई गई इमेज से मिलता-जुलता दिखता है.

कलेक्शन व्यू वाले विजेट की झलक, विजेट में ठीक से दिखे पिकर, तो हम एक अलग लेआउट फ़ाइल बनाए रखने का सुझाव देते हैं, जो झलक देखें. इस अलग लेआउट फ़ाइल में असल विजेट लेआउट और नकली आइटम वाला प्लेसहोल्डर कलेक्शन व्यू. उदाहरण के लिए, कई फ़र्ज़ी सूची आइटम के साथ प्लेसहोल्डर 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>

नकली सूची आइटम देने के लिए, लेआउट को कई बार शामिल किया जा सकता है. हालांकि, इससे हर सूची आइटम एक जैसा हो जाता है. सूची में यूनीक आइटम जोड़ने के लिए, यह तरीका अपनाएं:

  1. टेक्स्ट वैल्यू के लिए एट्रिब्यूट का सेट बनाएं:

    <resources>
        <attr name="widgetTitle" format="string" />
        <attr name="widgetContent" format="string" />
    </resources>
    
  2. टेक्स्ट सेट करने के लिए, इन एट्रिब्यूट का इस्तेमाल करें:

    <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>
    
  3. झलक के लिए ज़रूरत के मुताबिक स्टाइल बनाएं. हर स्टाइल में वैल्यू फिर से तय करें:

    <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>
    
  4. झलक दिखाने वाले लेआउट में नकली आइटम पर स्टाइल लागू करें:

    <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>