ANR

जब किसी Android ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) थ्रेड लंबे समय तक ब्लॉक रहता है, तो "ऐप्लिकेशन जवाब नहीं दिया जा रहा है" (एएनआर) की गड़बड़ी ट्रिगर होती है. अगर ऐप्लिकेशन फ़ोरग्राउंड में है, तो सिस्टम, उपयोगकर्ता को एक डायलॉग दिखाता है, जैसा कि पहली इमेज में दिखाया गया है. ANR संवाद से हमें उपयोगकर्ता को ऐप्लिकेशन को ज़बरदस्ती बंद करने का विकल्प भी देता है.

पहली इमेज. उपयोगकर्ता को ANR वाला डायलॉग दिखाया गया

पहला डायग्राम. उपयोगकर्ता को ANR वाला डायलॉग दिखाया गया

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

आपके ऐप्लिकेशन के लिए ANR वाली गड़बड़ी, इनमें से किसी एक स्थिति में ट्रिगर होती है:

  • इनपुट भेजने का समय खत्म हो गया: अगर आपके ऐप्लिकेशन ने किसी इनपुट का जवाब नहीं दिया है इवेंट (जैसे कि बटन दबाने या स्क्रीन टच करने जैसी गतिविधि) 5 सेकंड के अंदर हो गया.
  • सेवा लागू करना: अगर आपके ऐप्लिकेशन ने जिस सेवा का एलान किया है वह खत्म नहीं हो सकती Service.onCreate() एक्ज़ीक्यूट किया जा रहा है और Service.onStartCommand()/Service.onBind() हो जाएगा.
  • Service.startForeground() कॉल नहीं किया जाता: अगर आपका ऐप्लिकेशन, फ़ोरग्राउंड में कोई नई सेवा शुरू करने के लिए Context.startForegroundService(), लेकिन फिर सेवा 5 सेकंड के अंदर startForeground() को कॉल नहीं करती.
  • इंटेंट का ब्रॉडकास्ट: अगर कोई BroadcastReceiver तय समय में एक्ज़ीक्यूट नहीं किया जा सका. अगर ऐप्लिकेशन में कोई फ़ोरग्राउंड में गतिविधि है, तो यह टाइम आउट 5 सेकंड का है.
  • JobScheduler इंटरैक्शन: अगर कोई JobService वापस नहीं लौटता है कुछ ही दिनों में JobService.onStartJob() या JobService.onStopJob() से सेकंड या उपयोगकर्ता की ओर से शुरू किया गया जॉब शुरू हो जाता है और आपका ऐप्लिकेशन कुछ दिनों में JobService.setNotification() को कॉल नहीं करता JobService.onStartJob() को कॉल करने के कुछ सेकंड बाद. ऐप्लिकेशन टारगेटिंग के लिए Android 13 और उससे पहले के वर्शन के लिए, ANR वाली गड़बड़ियां साइलेंट मोड में रहती हैं और ऐप्लिकेशन को रिपोर्ट नहीं की जातीं. Android 14 और उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन में, ANR से जुड़ी गड़बड़ियां साफ़ तौर पर दिखती हैं और को ऐप को रिपोर्ट किया गया.

अगर आपके ऐप्लिकेशन में ANR की समस्या आ रही है, तो इस लेख में दिए गए दिशा-निर्देशों का इस्तेमाल करके, ये काम किए जा सकते हैं समस्या का पता लगाकर उसे ठीक करें.

समस्या का पता लगाना

अगर आपने पहले ही अपना ऐप्लिकेशन पब्लिश कर दिया है, तो 'Android की ज़रूरी जानकारी' में जाकर, अपने ऐप्लिकेशन से जुड़े एएनआर की जानकारी देखी जा सकती है. आप चाहें, तो अन्य फ़ील्ड में ANR का पता लगाने के लिए इस्तेमाल किए जाने वाले टूल. हालांकि, ध्यान रखें कि तीसरे पक्ष के टूल, ANR की रिपोर्ट नहीं कर सकते 'Android की ज़रूरी जानकारी' से अलग, Android के पुराने वर्शन (Android 10 और इससे पहले के वर्शन).

Android की ज़रूरी जानकारी

'Android की ज़रूरी जानकारी' की मदद से, अपने ऐप्लिकेशन के ANR रेट पर नज़र रखी जा सकती है और उसे बेहतर बनाया जा सकता है. 'Android की ज़रूरी जानकारी' में, ANR रेट के कई विकल्पों का आकलन किया जाता है:

  • ANR रेट: हर दिन के ऐसे सक्रिय उपयोगकर्ताओं का प्रतिशत होता है जो किसी भी तरह की ANR वाली गड़बड़ी का सामना करना पड़ा.
  • यूज़र पर्सीव्ड ANR रेट: हर दिन के सक्रिय उपयोगकर्ताओं का प्रतिशत जिन्हें कम से कम एक बार यूज़र-पर्सीव्ड ANR की गड़बड़ी का सामना करना पड़ा. वर्तमान में केवल के ANR टाइप Input dispatching timed out को यूज़र-पर्सीव्ड ANR माना जाता है.
  • एक से ज़्यादा ANR रेट: आपके हर दिन के ऐसे सक्रिय उपयोगकर्ताओं का प्रतिशत जो कम से कम दो ANR का सामना करना पड़ा.

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

यूज़र-पर्सीव्ड ANR रेट, सबसे ज़रूरी होता है. इसका मतलब है कि यह आपके ऐप्लिकेशन की Google Play पर आपके ऐप्लिकेशन को खोजे जाने लायक बनाया जा सकता है. यह अहम है, क्योंकि इसमें एएनआर वाली गड़बड़ियां होती हैं की गिनती हमेशा तब होती है, जब उपयोगकर्ता ऐप्लिकेशन के साथ जुड़ा रहता है. इस वजह से समस्या है.

Play ने इस मेट्रिक पर, ऐप्लिकेशन की खराब परफ़ॉर्मेंस के दो थ्रेशोल्ड तय किए हैं:

  • ऐप्लिकेशन की खराब परफ़ॉर्मेंस का थ्रेशोल्ड: हर दिन के सक्रिय उपयोगकर्ताओं का कम से कम 0.47% सभी डिवाइस मॉडल पर यूज़र-पर्सीव्ड ANR का सामना करना.
  • हर डिवाइस के हिसाब से ऐप्लिकेशन की खराब परफ़ॉर्मेंस का थ्रेशोल्ड: हर दिन के सक्रिय उपयोगकर्ताओं में से कम से कम 8% एक ही डिवाइस मॉडल के लिए यूज़र-पर्सीव्ड ANR का अनुभव हुआ हो.

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

'Android की ज़रूरी जानकारी' की मदद से, आपको सूचना मिल सकती है. इसके लिए, Play Console, जब आपका ऐप्लिकेशन बहुत ज़्यादा एएनआर दिखा रहा हो.

Google Play, 'Android की ज़रूरी जानकारी' का डेटा कैसे इकट्ठा करता है, इस बारे में जानने के लिए Play Console दस्तावेज़.

एएनआर का पता लगाएं

एएनआर का पता लगाते समय, कुछ सामान्य पैटर्न का इस्तेमाल किया जाता है:

  • ऐप्लिकेशन, मुख्य थ्रेड पर I/O से धीमी प्रोसेस कर रहा है.
  • ऐप्लिकेशन, मुख्य थ्रेड पर लंबा कैलकुलेशन कर रहा है.
  • मुख्य थ्रेड, किसी अन्य प्रोसेस को सिंक्रोनस बाइंडर कॉल कर रहा है और उस अन्य प्रक्रिया को वापस लौटाने में बहुत समय लग रहा है.
  • सिंक किए गए ब्लॉक को लंबे समय तक इंतज़ार करने के लिए, मुख्य थ्रेड को ब्लॉक किया गया है किसी दूसरे थ्रेड पर चल रही कार्रवाई.
  • मुख्य थ्रेड किसी दूसरे थ्रेड के साथ एक डेडलॉक में है या आपके प्रोसेस या बाइंडर कॉल के ज़रिए करना होगा. मुख्य थ्रेड को लेकिन एक घातक स्थिति में है. ज़्यादा जानकारी के लिए, Wikipedia पर Deadlock देखें.

नीचे दी गई तकनीकें, ANR वाली गड़बड़ियों की वजह का पता लगाने में आपकी मदद कर सकती हैं.

हेल्थस्टैट्स

HealthStats इसके बारे में मेट्रिक उपलब्ध कराता है उपयोगकर्ता और सिस्टम के कुल समय, सीपीयू के समय, नेटवर्क, रेडियो आँकड़े, स्क्रीन चालू/बंद समय, और जागने के अलार्म. यह काम कर सकता है सीपीयू के कुल इस्तेमाल और बैटरी तेज़ी से खर्च होने की दर को मापने में मदद मिलती है.

डीबग

Debug, Android ऐप्लिकेशन की जांच करने में मदद करता है इसमें जैंक की पहचान करने के लिए, ट्रेस करने और ऐलोकेशन की संख्या तय करने शामिल हैं. और ऐप में समय नहीं है. रनटाइम और नेटिव मेमोरी पाने के लिए, Debug का भी इस्तेमाल किया जा सकता है और मेमोरी मेट्रिक का इस्तेमाल करें. इससे मेमोरी फ़ुटप्रिंट की पहचान करने में मदद मिल सकती है. एक खास प्रोसेस के बारे में बताया गया है.

ऐप्लिकेशन बाहर निकलने की जानकारी

ApplicationExitInfo उपलब्ध है Android 11 (एपीआई लेवल 30) या उसके बाद के वर्शन पर काम करता है. ऐप्लिकेशन के बाहर निकलने की वजह. इसमें ANR, कम मेमोरी, ऐप्लिकेशन बंद होना, सीपीयू का बहुत ज़्यादा इस्तेमाल, उपयोगकर्ता की रुकावटें, सिस्टम में रुकावटें या रनटाइम अनुमति में बदलाव.

स्ट्रिक्ट मोड

StrictMode का इस्तेमाल करने से, आपको यह जानकारी पाने में मदद मिलती है ऐप्लिकेशन को डेवलप करते समय, मुख्य थ्रेड में गलती से I/O कार्रवाइयां की जा सकती हैं. StrictMode का इस्तेमाल किया जा सकता है ऐप्लिकेशन या गतिविधि स्तर पर.

बैकग्राउंड ANR डायलॉग चालू करें

Android, उन ऐप्लिकेशन के लिए ANR डायलॉग दिखाता है जिन्हें ब्रॉडकास्ट प्रोसेस करने में बहुत ज़्यादा समय लगता है सिर्फ़ तब मैसेज भेज सकता है, जब डिवाइस के डेवलपर में सभी ANR दिखाएं चालू हो विकल्प. इस वजह से, बैकग्राउंड में ANR की गड़बड़ी वाले डायलॉग हमेशा उपयोगकर्ता, लेकिन ऐप्लिकेशन अब भी परफ़ॉर्मेंस से जुड़ी समस्याओं का सामना कर सकता है.

ट्रेसव्यू

Traceview का इस्तेमाल करके, अपने मौजूदा ऐप्लिकेशन की परफ़ॉर्मेंस की जानकारी हासिल की जा सकती है. इसके लिए, इस्तेमाल के उदाहरण देखें और उन जगहों की पहचान करें जहां मुख्य थ्रेड व्यस्त है. जानकारी के लिए Traceview का इस्तेमाल करने के तरीके के बारे में जानने के लिए, Traceview की मदद से प्रोफ़ाइल बनाना और dmtracedump.

ट्रेस फ़ाइल खींचें

ANR की गड़बड़ी का पता चलने पर, Android, ट्रेस की जानकारी सेव करता है. पुराने ओएस पर रिलीज़, डिवाइस पर एक /data/anr/traces.txt फ़ाइल है. ओएस के नए वर्शन में, कई /data/anr/anr_* फ़ाइलें होती हैं. किसी डिवाइस या एम्युलेटर से, ANR के ट्रेस ऐक्सेस करने के लिए इनका इस्तेमाल किया जा सकता है: रूट के तौर पर Android डीबग ब्रिज (adb):

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

'गड़बड़ी की जानकारी लें' टूल का इस्तेमाल करके, किसी फ़िज़िकल डिवाइस से गड़बड़ी की रिपोर्ट कैप्चर की जा सकती है या अपने डिवाइस पर adb Bugreport कमांड डेवलपमेंट मशीन पर काम करता था. ज़्यादा जानकारी के लिए, गड़बड़ी को कैप्चर करना और पढ़ना देखें रिपोर्ट.

समस्याओं को ठीक करना

समस्या की पहचान करने के बाद, इस सेक्शन में दी गई सलाह का इस्तेमाल करके, आम तौर पर मिलने वाली समस्याओं को ठीक करती है.

मुख्य थ्रेड पर धीमा कोड

अपने कोड में उन जगहों की पहचान करें जहां ऐप्लिकेशन का मुख्य थ्रेड ज़्यादा समय के लिए व्यस्त है 5 सेकंड से भी कम हो. अपने ऐप्लिकेशन में इस्तेमाल के संदिग्ध उदाहरण देखें और फिर से कोशिश करें एएनआर के बारे में फिर से बताएं.

उदाहरण के लिए, दूसरी इमेज में ट्रेसव्यू टाइमलाइन दिखती है, जहां मुख्य थ्रेड व्यस्त है से ज़्यादा हो सकता है.

दूसरी इमेज. ट्रेस व्यू टाइमलाइन, एक व्यस्त मुख्य डेटा को दिखा रही है
थ्रेड

दूसरा डायग्राम. ट्रेस व्यू की टाइमलाइन, एक व्यस्त मुख्य थ्रेड को दिखा रही है

इमेज 2 में दिखाया गया है कि ज़्यादातर आपत्तिजनक कोड onClick(View) हैंडलर, जैसा कि इस कोड उदाहरण में दिखाया गया है:

Kotlin

override fun onClick(v: View) {
    // This task runs on the main thread.
    BubbleSort.sort(data)
}

Java

@Override
public void onClick(View view) {
    // This task runs on the main thread.
    BubbleSort.sort(data);
}

इस स्थिति में, आपको मुख्य थ्रेड में चल रहे काम को किसी वर्कर में ले जाना चाहिए थ्रेड. Android फ़्रेमवर्क में ऐसी क्लास शामिल हैं जिनसे इस टास्क को दूसरे चरण में ले जाने में मदद मिल सकती है एक वर्कर थ्रेड में जोड़ा जा सकता है. कर्मचारी देखें ज़्यादा जानकारी के लिए थ्रेड जानकारी.

मुख्य थ्रेड पर IO है

मुख्य थ्रेड पर IO कार्रवाइयों को एक्ज़ीक्यूट करना, धीमी प्रोसेस की आम वजह है की वजह से ANR हो सकता है. सभी IO को ट्रांसफ़र करने का सुझाव दिया जाता है जैसा कि पिछले सेक्शन में दिखाया गया है.

नेटवर्क और स्टोरेज कार्रवाइयां, IO कार्रवाइयों के कुछ उदाहरण हैं. ज़्यादा के लिए जानकारी, नेटवर्क परफ़ॉर्म कर रहा है कार्रवाइयां और सेव किया जा रहा है डेटा.

लॉक का विवाद

कुछ मामलों में, ANR की गड़बड़ी की वजह बनने वाला काम, सीधे ऐप का मुख्य थ्रेड है. अगर कोई वर्कर थ्रेड, ऐसे संसाधन पर लॉक रखता है जो मुख्य थ्रेड को अपना काम पूरा करने की ज़रूरत होती है, तब ANR हो सकता है.

उदाहरण के लिए, तीसरी इमेज में एक ट्रेसव्यू टाइमलाइन दिखती है, जहां ज़्यादातर काम एक वर्कर थ्रेड पर किया गया.

तीसरी इमेज. किसी कर्मचारी पर किया जा रहा काम दिखाने वाली ट्रेसव्यू टाइमलाइन
थ्रेड

तीसरी इमेज. किसी कर्मचारी पर किया जा रहा काम दिखाने वाली ट्रेसव्यू टाइमलाइन थ्रेड

हालांकि, अगर आपके उपयोगकर्ताओं को अब भी ANR की समस्या आ रही है, तो आपको Android Device Monitor में मुख्य थ्रेड. आम तौर पर, मुख्य थ्रेड RUNNABLE बताएं कि यह यूआई को अपडेट करने के लिए तैयार है और सामान्य तौर पर रिस्पॉन्सिव है.

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

चौथी इमेज. मॉनिटर में मुख्य थ्रेड
स्थिति

चौथी इमेज. मॉनिटर की स्थिति में मुख्य थ्रेड

नीचे दिया गया ट्रेस, ऐप्लिकेशन का मुख्य थ्रेड दिखाता है. इसे ब्लॉक किया गया है संसाधन:

...
AsyncTask #2" prio=5 tid=18 Runnable
  | group="main" sCount=0 dsCount=0 obj=0x12c333a0 self=0x94c87100
  | sysTid=25287 nice=10 cgrp=default sched=0/0 handle=0x94b80920
  | state=R schedstat=( 0 0 0 ) utm=757 stm=0 core=3 HZ=100
  | stack=0x94a7e000-0x94a80000 stackSize=1038KB
  | held mutexes= "mutator lock"(shared held)
  at com.android.developer.anrsample.BubbleSort.sort(BubbleSort.java:8)
  at com.android.developer.anrsample.MainActivity$LockTask.doInBackground(MainActivity.java:147)
  - locked <0x083105ee> (a java.lang.Boolean)
  at com.android.developer.anrsample.MainActivity$LockTask.doInBackground(MainActivity.java:135)
  at android.os.AsyncTask$2.call(AsyncTask.java:305)
  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
  at java.lang.Thread.run(Thread.java:761)
...

ट्रेस की समीक्षा करने से, आपको मुख्य थ्रेड को ब्लॉक करने वाले कोड का पता लगाने में मदद मिल सकती है. नीचे दिए गए कोड की वजह से वह लॉक पकड़ा जाता है जो मुख्य विंडो को ब्लॉक करता है पिछले ट्रेस में थ्रेड:

Kotlin

override fun onClick(v: View) {
    // The worker thread holds a lock on lockedResource
    LockTask().execute(data)

    synchronized(lockedResource) {
        // The main thread requires lockedResource here
        // but it has to wait until LockTask finishes using it.
    }
}

class LockTask : AsyncTask<Array<Int>, Int, Long>() {
    override fun doInBackground(vararg params: Array<Int>): Long? =
            synchronized(lockedResource) {
                // This is a long-running operation, which makes
                // the lock last for a long time
                BubbleSort.sort(params[0])
            }
}

Java

@Override
public void onClick(View v) {
    // The worker thread holds a lock on lockedResource
   new LockTask().execute(data);

   synchronized (lockedResource) {
       // The main thread requires lockedResource here
       // but it has to wait until LockTask finishes using it.
   }
}

public class LockTask extends AsyncTask<Integer[], Integer, Long> {
   @Override
   protected Long doInBackground(Integer[]... params) {
       synchronized (lockedResource) {
           // This is a long-running operation, which makes
           // the lock last for a long time
           BubbleSort.sort(params[0]);
       }
   }
}

दूसरा उदाहरण ऐप्लिकेशन का मुख्य थ्रेड है, जो वर्कर थ्रेड में मौजूद है, जैसा कि इस कोड में दिखाया गया है. ध्यान दें कि wait() और Kotlin में notify() को इस्तेमाल करने का सुझाव नहीं दिया जाता है. इस पैटर्न के अपने अलग तरीके हैं एक साथ कई काम करने के लिए. Kotlin का इस्तेमाल करते समय, आपको Kotlin के हिसाब से सिस्टम का इस्तेमाल किया जा सकता है.

Kotlin

fun onClick(v: View) {
    val lock = java.lang.Object()
    val waitTask = WaitTask(lock)
    synchronized(lock) {
        try {
            waitTask.execute(data)
            // Wait for this worker thread’s notification
            lock.wait()
        } catch (e: InterruptedException) {
        }
    }
}

internal class WaitTask(private val lock: java.lang.Object) : AsyncTask<Array<Int>, Int, Long>() {
    override fun doInBackground(vararg params: Array<Int>): Long? {
        synchronized(lock) {
            BubbleSort.sort(params[0])
            // Finished, notify the main thread
            lock.notify()
        }
    }
}

Java

public void onClick(View v) {
   WaitTask waitTask = new WaitTask();
   synchronized (waitTask) {
       try {
           waitTask.execute(data);
           // Wait for this worker thread’s notification
           waitTask.wait();
       } catch (InterruptedException e) {}
   }
}

class WaitTask extends AsyncTask<Integer[], Integer, Long> {
   @Override
   protected Long doInBackground(Integer[]... params) {
       synchronized (this) {
           BubbleSort.sort(params[0]);
           // Finished, notify the main thread
           notify();
       }
   }
}

ऐसी कुछ और स्थितियां भी हैं जो मुख्य थ्रेड को ब्लॉक कर सकती हैं. इनमें ये मामले शामिल हैं ऐसे थ्रेड जो Lock का इस्तेमाल करते हैं, Semaphore, साथ ही, एक रिसॉर्स पूल भी (जैसे कि डेटाबेस कनेक्शन का पूल) या अन्य म्यूचुअल एक्सक्लूज़न (म्यूटक्स) मैकेनिज़्म शामिल करें.

आपको उन लॉक का आकलन करना चाहिए जो आम तौर पर, संसाधनों पर आपके ऐप्लिकेशन के पास होते हैं, लेकिन अगर आपको ANR से जुड़ी समस्याओं से बचना है, तो रिसॉर्स के लॉक देखें मुख्य थ्रेड के लिए ज़रूरी है.

पक्का करें कि ताले कम से कम समय के लिए होल्ड पर रखे जाएं या बेहतर तरीके से, यह मूल्यांकन किया जा सकता है कि ऐप्लिकेशन को होल्ड की ज़रूरत है या नहीं. अगर आप वर्कर थ्रेड की प्रोसेसिंग के आधार पर, यूज़र इंटरफ़ेस (यूआई) को कब अपडेट करना है, यह तय करने के लिए लॉक करें, ये तरीके अपनाते हैं onProgressUpdate() और onPostExecute() कर्मचारी और मुख्य थ्रेड के बीच बातचीत करने के लिए.

डेडलॉक

एक डेडलॉक तब होता है, जब कोई थ्रेड ज़रूरी होने पर वेटिंग स्टेट में पहुंच जाती है संसाधन किसी दूसरे थ्रेड के पास है, जो उस संसाधन का इंतज़ार कर रहा है जो पहली थ्रेड. अगर ऐप्लिकेशन का मुख्य थ्रेड ऐसी स्थिति में है, तो ANR की संभावना हो सकती है होने वाला है.

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

ज़्यादा जानकारी के लिए, Deadlock और डेडलॉक की रोकथाम एल्गोरिदम चालू करें. विकिपीडिया.

धीमे ब्रॉडकास्ट रिसीवर

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

ANR वाली गड़बड़ी, इन मामलों में होती है:

  • ब्रॉडकास्ट रिसीवर ने अभी तक अपने onReceive() काफ़ी आसान हो जाता है.
  • एक ब्रॉडकास्ट रिसीवर कॉल करता है goAsync() और कॉल न कर पाए finish() पूरी तरह कैसे PendingResult ऑब्जेक्ट है.

आपके ऐप्लिकेशन को इसमें सिर्फ़ छोटी कार्रवाइयां करनी चाहिए onReceive() तरीका BroadcastReceiver. हालांकि, अगर आपके ऐप्लिकेशन को इंस्टॉल करना ज़्यादा मुश्किल है, पर होने वाला है, इसलिए आपको यह टास्क IntentService.

Traceview जैसे टूल का इस्तेमाल करके, यह पता लगाया जा सकता है कि आपका ब्रॉडकास्ट रिसीवर काम करता है या नहीं ऐप्लिकेशन के मुख्य थ्रेड पर लंबे समय तक चलने वाली कार्रवाइयां. उदाहरण के लिए, छठी इमेज में दिखाए गए ब्रॉडकास्ट रिसीवर की टाइमलाइन, जो मुख्य थ्रेड पर मैसेज को प्रोसेस करती है करीब 100 सेकंड के लिए.

पांचवीं इमेज. ट्रेसव्यू टाइमलाइन की मदद से, मुख्य फ़ंक्शन के साथ `BroadcastReceiver` काम दिखाया गया है
थ्रेड

पांचवी इमेज. ट्रेसव्यू टाइमलाइन, यहां पर BroadcastReceiver के काम को दिखा रही है मुख्य थ्रेड

ऐसा तब हो सकता है, जब onReceive() का तरीका BroadcastReceiver, जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है:

Kotlin

override fun onReceive(context: Context, intent: Intent) {
    // This is a long-running operation
    BubbleSort.sort(data)
}

Java

@Override
public void onReceive(Context context, Intent intent) {
    // This is a long-running operation
    BubbleSort.sort(data);
}

ऐसी परिस्थितियों में, हमारा सुझाव है कि लंबे समय तक चलने वाले ऑपरेशन को IntentService, क्योंकि यह वर्कर थ्रेड को एक्ज़ीक्यूट किया जा सकता है. नीचे दिया गया कोड दिखाता है कि IntentService लंबे समय तक चलने वाली कार्रवाई:

Kotlin

override fun onReceive(context: Context, intent: Intent) {
    Intent(context, MyIntentService::class.java).also { intentService ->
        // The task now runs on a worker thread.
        context.startService(intentService)
    }
}

class MyIntentService : IntentService("MyIntentService") {
    override fun onHandleIntent(intent: Intent?) {
        BubbleSort.sort(data)
    }
}

Java

@Override
public void onReceive(Context context, Intent intent) {
    // The task now runs on a worker thread.
    Intent intentService = new Intent(context, MyIntentService.class);
    context.startService(intentService);
}

public class MyIntentService extends IntentService {
   @Override
   protected void onHandleIntent(@Nullable Intent intent) {
       BubbleSort.sort(data);
   }
}

डाइग्नोस्टिक टूल का इस्तेमाल करने से IntentService, लंबे समय से डेटा इस्तेमाल करके ऑपरेशन को मुख्य थ्रेड के बजाय किसी वर्कर थ्रेड पर किया जाता है. सातवीं इमेज ट्रेसव्यू टाइमलाइन में वर्कर थ्रेड में टाला गया काम दिखाता है.

छठी इमेज. ट्रेस व्यू टाइमलाइन,
वर्कर थ्रेड

छठी इमेज. ट्रेस व्यू टाइमलाइन, वर्कर थ्रेड

आपका ब्रॉडकास्ट रिसीवर इनका इस्तेमाल कर सकता है goAsync() का इस्तेमाल करें, ताकि सिस्टम को यह बताया जा सके कि उसे मैसेज प्रोसेस करने में ज़्यादा समय लगेगा. हालांकि, तुम्हें कॉल करना चाहिए finish() पूरी तरह कैसे PendingResult ऑब्जेक्ट है. नीचे दिए गए उदाहरण में, फ़िनिश() को कॉल करने का तरीका बताया गया है, ताकि सिस्टम ब्रॉडकास्ट रिसीवर को रीसाइकल करें और एएनआर वाली गड़बड़ी से बचें:

Kotlin

val pendingResult = goAsync()

object : AsyncTask<Array<Int>, Int, Long>() {
    override fun doInBackground(vararg params: Array<Int>): Long? {
        // This is a long-running operation
        BubbleSort.sort(params[0])
        pendingResult.finish()
        return 0L
    }
}.execute(data)

Java

final PendingResult pendingResult = goAsync();
new AsyncTask<Integer[], Integer, Long>() {
   @Override
   protected Long doInBackground(Integer[]... params) {
       // This is a long-running operation
       BubbleSort.sort(params[0]);
       pendingResult.finish();
   }
}.execute(data);

हालांकि, कोड को धीमे ब्रॉडकास्ट रिसीवर से दूसरे थ्रेड में ले जाया जा सकता है और goAsync() का इस्तेमाल किया जा रहा है अगर ब्रॉडकास्ट बैकग्राउंड में हो, तो ANR की गड़बड़ी ठीक नहीं होगी. ANR टाइम आउट अब भी लागू होगा.

गेमगतिविधि

GameActivity लाइब्रेरी में ANR की संख्या कम हो गई है लिखे गए गेम और ऐप्लिकेशन की केस स्टडी C या C++ में देखें. अगर आप अपनी मौजूदा नेटिव गतिविधि को GameActivity से बदलते हैं, तो यूज़र इंटरफ़ेस (यूआई) थ्रेड के ब्लॉक होने की समस्या को कम किया जा सकता है और कुछ ANRs को रोका जा सकता है.

ANR की गड़बड़ियों के बारे में ज़्यादा जानकारी के लिए, यहां देखें अपने ऐप्लिकेशन को रिस्पॉन्सिव रखना. ज़्यादा के लिए थ्रेड के बारे में जानकारी, देखें थ्रेडिंग की परफ़ॉर्मेंस.