दिलचस्प पोस्ट
क्या PHP में कचरा संग्रह है? सूचक सी से सरणी का आकार प्राप्त करना पथ उपसर्ग \\? \ \ और \\? फ्रेमवर्क 3.5 में सर्वर टैग <% =%> के साथ दृश्यमान संपत्ति सेट करें कैसे एक फ़ाइल से integers के समूह को पढ़ने के लिए, लाइन में लाइन में सी ++ आप पायथन में SQLite तालिका / स्तंभ नामों के लिए स्ट्रिंग कैसे बचते हैं? कंसोल लाइन से इनपुट कैसे पढ़ा जाए? जांच करें कि घटना मानव द्वारा शुरू हो रही है या नहीं फेसबुक एंड्रॉइड इंस्टॉल है या नहीं ImageIO एक JPEG फ़ाइल लिखने में सक्षम नहीं है एक्सएमएल सीरियललाइज़ेशन और नेमस्पेस उपसर्ग स्विफ्ट: शब्दकोशों के अंदर एआरएफ़ को संशोधित करना जावास्क्रिप्ट में वैकल्पिक पैरामीटरों को संभालना मनोहर संग्रह: गिनती और खाली पता लगाता है एसीआईएनसीसी / इंतजार के जरिए WCF सेवा को कॉल करने के लिए पैटर्न

एसिंक टास्क गतिविधि को नष्ट होने पर भी नहीं रोकेंगे

मेरे पास एक एसिंककास ऑब्जेक्ट है जो क्रियाकलाप निष्पादित करता है, जब गतिविधि बनाई जाती है और पृष्ठभूमि में सामान (100 छवियों तक डाउनलोड) करता है। सब कुछ ठीक है, लेकिन यह अजीब व्यवहार है जो मैं समझ नहीं पा रहा हूं।

उदाहरण के लिए: जब एंड्रॉइड स्क्रीन की ओरिएंटेशन बदलता है तो गतिविधि नष्ट हो जाती है और फिर से बनाई जाती है। इसलिए मैं onRetainNonConfigurationInstance () विधि को ओवरराइड करता हूं और AsyncTask में निष्पादित सभी डाउनलोड किए गए डेटा को सहेजता हूं। ऐसा करने का मेरा उद्देश्य है कि AsyncTask हर बार क्रियाकलाप नष्ट हो जाता है- उन्मुखीकरण परिवर्तन के दौरान बनाया गया है, लेकिन जैसा कि मैं अपने लॉग में देख सकता हूं पिछले एसिनक टास्क अभी भी निष्पादित है। (डेटा सही रूप से सहेजा गया है हालांकि)

मैं भी गतिविधि के onDestroy () विधि में AsyncTask रद्द करने का प्रयास किया, लेकिन लॉग अभी भी चलने के रूप में AsyncTask दिखाते हैं।

यह वास्तव में अजीब व्यवहार है और वास्तव में आभारी होंगे अगर कोई मुझे ऐसिनक टास्क को रोकने / रद्द करने की सही प्रक्रिया बता सकता है।

धन्यवाद

Solutions Collecting From Web of "एसिंक टास्क गतिविधि को नष्ट होने पर भी नहीं रोकेंगे"

AFAIK, आप एक AsyncTask रोक नहीं सकते मुझे विश्वास नहीं है कि cancel() विधि कार्य करेगी यदि कार्य पहले से कार्यान्वित हो रहा है – जो काम करेगा अगर एक कतार में मुक्त करने के लिए कार्य प्रतीक्षा कर रहा है।

@ रमैन गाय द्वारा दिए गए उत्तर सही है। फिर भी, मैं सूचना के पूरक को जोड़ना चाहूंगा और एक लाइब्रेरी या 2 को एक सूचक देना चाहूंगा जो कि लंबे समय तक चलने के लिए इस्तेमाल किया जा सकता है AsyncTask और यहां तक ​​कि नेटवर्क उन्मुख asynctasks के लिए

AsyncTasks को पृष्ठभूमि में सामान करने के लिए डिज़ाइन किया गया है और हाँ, आप cancel विधि का उपयोग कर इसे रोक सकते हैं। जैसा कि आप इंटरनेट से सामग्री डाउनलोड करते हैं, मैं दृढ़ता से सुझाव देता हूं कि जब आपका आईओ अवरुद्ध राज्य होता है तो आप अपने धागा का ख्याल रखना । आपको अपने डाउनलोड को व्यवस्थित रूप से व्यवस्थित करना चाहिए:

 public void download() { //get the InputStream from HttpUrlConnection or any other //network related stuff while( inputStream.read(buffer) != -1 && !Thread.interrupted() ) { //copy data to your destination, a file for instance } //close the stream and other resources } 

थ्रेड. Thread.interrupted फ्लैग का उपयोग करने से आपके थ्रेड को उचित रूप से अवरुद्ध io स्थिति से बाहर निकलने में मदद मिलेगी। cancel विधि के एक शुभारंभ के लिए आपका धागा अधिक उत्तरदायी होगा।

AsyncTask डिजाइन दोष

लेकिन अगर आपका एसिंक टास्क बहुत अधिक समय तक रहता है, तो आपको 2 भिन्न मुद्दों का सामना करना होगा:

  1. क्रियाकलाप खराब गतिविधि जीवन चक्र से बंधे हैं और यदि आपकी गतिविधि मर जाती है तो आपको अपने असिनक टास्क का नतीजा नहीं मिलेगा। वास्तव में, हाँ, आप कर सकते हैं, लेकिन यह किसी न किसी तरह का रास्ता होगा।
  2. AsyncTask बहुत अच्छी तरह से प्रलेखित नहीं हैं एक भोली, हालांकि सहज ज्ञान युक्त, कार्यान्वयन और एक asynctask का उपयोग जल्दी से स्मृति लीक करने के लिए नेतृत्व कर सकते हैं।

रोबोस्पाइस , पुस्तकालय जो मैं पेश करना चाहता हूं, इस प्रकार के अनुरोधों को निष्पादित करने के लिए पृष्ठभूमि सेवा का उपयोग करता है। यह नेटवर्क अनुरोधों के लिए डिज़ाइन किया गया है। यह अतिरिक्त विशेषताओं को प्रदान करता है जैसे कि 'अनुरोधों के परिणामों के स्वत: कैशिंग।

यहाँ कारण है कि AsyncTasks लंबे चलने वाले कार्यों के लिए खराब हैं। निम्नलिखित तर्क रोबोस्पाइस प्रेरणाओं के प्रयासों से एक अनुकूलन है: ऐप जो बताता है कि रोबोस्स्पिस का उपयोग करने के कारण एंड्रॉइड प्लेटफ़ॉर्म पर आवश्यकताएं भर रही हैं।

AsyncTask और गतिविधि जीवन चक्र

AsyncTasks गतिविधि के उदाहरणों का जीवन चक्र का पालन नहीं करते हैं यदि आप किसी गतिविधि के अंदर एक AsyncTask प्रारंभ करते हैं और आप डिवाइस को घुमाते हैं, तो गतिविधि को नष्ट कर दिया जाएगा और एक नया उदाहरण बनाया जाएगा। लेकिन AsyncTask मर नहीं होगा यह तब तक जीवित रहेगा जब तक यह पूर्ण न हो जाए।

और जब यह पूरा हो जाता है, तो AsyncTask नई गतिविधि के UI को अपडेट नहीं करेगा। वास्तव में यह उस गतिविधि के पूर्व उदाहरण को अपडेट करता है जो अब प्रदर्शित नहीं किया जाता है। इस प्रकार की एक अपवाद हो सकती है java.lang.IllegalArgumentException: यदि आप उपयोग करते हैं तो देखें विंडो प्रबंधक से जुड़ा नहीं, उदाहरण के लिए, गतिविधि के अंदर एक दृश्य प्राप्त करने के लिए FindViewById।

मेमोरी लीक समस्या

आपके क्रियाकलापों के आंतरिक वर्गों के रूप में AsyncTasks बनाने के लिए यह बहुत सुविधाजनक है जैसा कि एसिंकटस्क को गतिविधि के विचारों में हेरफेर करने की आवश्यकता होगी जब कार्य पूर्ण हो जाएगा या प्रगति में, गतिविधि के आंतरिक वर्ग का उपयोग करना सुविधाजनक लगता है: आंतरिक वर्ग सीधे बाहरी कक्षा के किसी भी क्षेत्र का उपयोग कर सकते हैं।

इसके बावजूद, इसका मतलब है कि भीतर की कक्षा अपने बाह्य वर्ग के उदाहरण पर एक अदृश्य संदर्भ रखेगा: गतिविधि

लंबे समय से, यह एक स्मृति रिसाव पैदा करता है: अगर एसिंकटस्क लंबे समय तक रहता है, तो यह गतिविधि को "जीवित" रखता है जबकि एंड्रॉइड इसे से छुटकारा दिलाना चाहती है क्योंकि अब इसे प्रदर्शित नहीं किया जा सकता है गतिविधि कचरा एकत्रित नहीं हो सकती और यह डिवाइस पर संसाधनों को संरक्षित रखने के लिए एंड्रॉइड के लिए एक केंद्रीय तंत्र है।

आपके काम की प्रगति खो जाएगी

आप लंबे समय तक चलने वाली एसिंक्टकॉस्क बनाने के लिए कुछ सर्किटों का उपयोग कर सकते हैं और गतिविधि के जीवन चक्र के हिसाब से उसके जीवन चक्र का प्रबंधन कर सकते हैं। आप या तो अपनी गतिविधि की onStop पद्धति में AsyncTask को रद्द कर सकते हैं या आप अपने एसिंक कार्य को समाप्त कर सकते हैं, अपनी प्रगति को ढूढ़ नहीं सकते हैं और अपनी गतिविधि के अगले आवेश को फिर से लिंक कर सकते हैं।

यह संभव है और हम कैसे दिखाते हैं कि रोबोपस्पिस प्रेरणाओं में, लेकिन यह जटिल हो जाता है और कोड वास्तव में सामान्य नहीं है। इसके अलावा, आप अपने कार्य की प्रगति को खो देंगे यदि उपयोगकर्ता गतिविधि को छोड़ देता है और वापस आ जाता है। यह वही मुद्दा लोडर के साथ प्रकट होता है, हालांकि यह उपरोक्त उल्लेखित समाधान के साथ असिनक टास्क के समान सरल होगा।

एंड्रॉइड सेवा का उपयोग करना

सबसे अच्छा विकल्प अपने लंबे चलने वाले पृष्ठभूमि कार्यों को निष्पादित करने के लिए एक सेवा का उपयोग करना है। और यह वास्तव में रोबोस्स्पस द्वारा प्रस्तावित समाधान है फिर, यह नेटवर्किंग के लिए डिज़ाइन किया गया है लेकिन इसे गैर-नेटवर्क से संबंधित सामान तक बढ़ाया जा सकता है इस पुस्तकालय में बड़ी संख्या में विशेषताएं हैं

आप इन्फोग्राफिक्स के लिए 30 सेकंड से भी कम समय में इसका विचार भी प्राप्त कर सकते हैं।


लंबे समय से चलने वाले कार्यों के लिए असिनक टास्क का इस्तेमाल करना वास्तव में बहुत ही बुरा विचार है। फिर भी, वे कम जीवित लोगों के लिए ठीक हैं जैसे 1 या 2 सेकेंड के बाद एक दृश्य को अपडेट करना।

मैं आपको रोबोस्पीस प्रेरणा ऐप डाउनलोड करने के लिए प्रोत्साहित करता हूं , यह वास्तव में इस गहराई में बताता है और कुछ नेटवर्क से संबंधित सामग्री को करने के विभिन्न तरीकों के नमूने और प्रदर्शन प्रदान करता है।


यदि आप गैर-नेटवर्क से संबंधित कार्यों के लिए रोबोस्स्पिस के विकल्प की तलाश कर रहे हैं (उदाहरण के लिए बिना कैशिंग), तो आप टेप पर भी नजर डाल सकते हैं।

रोमेन गाय सही है वास्तव में, किसी भी मामले में अपना काम पूरा करने के लिए एक async कार्य जिम्मेदार है। इंटरप्ट सबसे अच्छा तरीका नहीं है, इसलिए आपको निरंतर जांच करनी चाहिए कि कोई आप को अपना कार्य रद्द करना या रोकना चाहता है।

मान लीजिए आपका AsyncTask कई बार एक पाश में कुछ करता है तब आपको जांचना चाहिए कि प्रत्येक लूप में isCancelled() है

 while ( true ) { if ( isCancelled()) break; doTheTask(); } 

doTheTask() आपका असली काम है और इससे पहले कि आप इसे प्रत्येक लूप में करते हैं, आप doTheTask() कि आपका कार्य रद्द होना चाहिए।

आम तौर पर आपको अपने AsyncTask क्लास में एक झंडा निर्धारित करना चाहिए या अपने doInBackground() से एक उचित परिणाम लौटा देना चाहिए, ताकि आपके onPostExecute() , आप यह जांच सकें कि क्या आप चाहते हैं कि आप क्या कर सकते हैं या आपके काम को बीच में रद्द कर दिया गया है या नहीं।

निम्नलिखित आपकी समस्या का समाधान नहीं करता, लेकिन इसे रोकता है: ऐप मेनिफेस्ट में ऐसा करें:

  <activity android:name=".(your activity name)" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden|screenSize" > //this line here </activity> 

जब आप इसे जोड़ते हैं, तो आपकी गतिविधि कॉन्फ़िगरेशन परिवर्तन पर पुनः लोड नहीं करती है, और यदि आप कुछ परिवर्तन करना चाहते हैं, जब ओरिएंटेशन में परिवर्तन होता है तो आप गतिविधि की निम्नलिखित विधि को ओवरराइड करते हैं:

 @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); //your code here } 

गतिविधि उन्मुखीकरण परिवर्तन पर बनाया गया है, हाँ सच है कि। लेकिन जब भी यह घटना होती है तो आप असिनक्टस्क जारी रख सकते हैं।

आप इसे जांचते हैं

 @Override protected void onCreate(Bundle savedInstanceState) { if ( savedInstanceState == null ) { startAsyncTask() } else { // ** Do Nothing async task will just continue. } } 

-cheers

यदि asynctask थ्रेड पूल (समानांतर प्रसंस्करण) में नहीं है तो आप asynctask निष्पादित करना बंद नहीं कर सकते क्योंकि यह पहले से CPU द्वारा निष्पादित किया जा रहा है और आपका स्टॉप या रद्द कमांड सीपीयू के बाद निष्पादित हो जाएगा (सीपीयू एएसआईएनक्टस्क के साथ किया जाता है)। हालांकि यह थ्रेड पूल में है, कार्य कतारबद्ध होंगे और एक-एक करके इसे निष्पादित किया जाएगा। इसलिए यदि आपके रद्द कमांड कमान में एसिंक कार्य निष्पादित करते हैं, तो यह आपके एसिंक कार्य को रोक सकता है।

एमवीसी दृष्टिकोण से, गतिविधि नियंत्रक है ; कंट्रोलर के प्रदर्शन के लिए यह गलत है, जो व्यू (एंड्रॉइड.दृश्य.दृश्य से व्युत्पन्न, आमतौर पर आप केवल मौजूदा कक्षाओं का पुन: उपयोग कर सकते हैं) को जीवित करते हैं। इसलिए, AsyncTasks प्रारंभ करने के लिए यह मॉडल की जिम्मेदारी होना चाहिए।

आप सभी AsyncTasks के साथ प्रक्रिया को मारने के लिए इस पोस्ट से class MagicAppRestart उपयोग कर सकते हैं; एंड्रॉइड गतिविधि स्टैक को बहाल करेगा (उपयोगकर्ता कुछ भी उल्लेख नहीं करेगा) यह ध्यान रखना महत्वपूर्ण है कि प्रोसेस पुनरारंभ होने से पहले ही एकमात्र सूचना कॉल हो रही है onPause() ; एंड्रॉइड ऐप के जीवन चक्र के तर्क के अनुसार, आपका आवेदन इस तरह के समापन के लिए तैयार होना चाहिए।

मैंने कोशिश की है, और यह काम करने लगता है फिर भी, फिलहाल मैं "अधिक सभ्य" तरीकों का उपयोग करने की योजना बना रहा हूँ जैसे कि आवेदन वर्ग से कमजोर संदर्भ (मेरे असिनक टास्क छोटे हैं और आशा है कि इतना मेमोरी लेने वाला नहीं)।

यहां कुछ कोड है जिसमें आप खेल सकते हैं:

MagicAppRestart.java

 package com.xyz; import android.app.Activity; import android.content.Intent; import android.os.Bundle; /** This activity shows nothing; instead, it restarts the android process */ public class MagicAppRestart extends Activity { // Do not forget to add it to AndroidManifest.xml // <activity android:name="your.package.name.MagicAppRestart"/> @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); System.exit(0); } public static void doRestart(Activity anyActivity) { anyActivity.startActivity(new Intent(anyActivity.getApplicationContext(), MagicAppRestart.class)); } } 

Com.xyz.AsyncTaskTestActivity के लिए एक नया एंड्रॉइड प्रोजेक्ट के लिए Eclipse बनाया गया बाकी है:

AsyncTaskTestActivity.java

 package com.xyz; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; public class AsyncTaskTestActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { Log.d("~~~~","~~~onCreate ~~~ "+this); super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void onStartButton(View view) { Log.d("~~~~","~~~onStartButton {"); class MyTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { // TODO Auto-generated method stub Log.d("~~~~","~~~doInBackground started"); try { for (int i=0; i<10; i++) { Log.d("~~~~","~~~sleep#"+i); Thread.sleep(200); } Log.d("~~~~","~~~sleeping over"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.d("~~~~","~~~doInBackground ended"); return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); taskDone(); } } MyTask task = new MyTask(); task.execute(null); Log.d("~~~~","~~~onStartButton }"); } private void taskDone() { Log.d("~~~~","\n\n~~~taskDone ~~~ "+this+"\n\n"); } public void onStopButton(View view) { Log.d("~~~~","~~~onStopButton {"); MagicAppRestart.doRestart(this); Log.d("~~~~","~~~onStopButton }"); } public void onPause() { Log.d("~~~~","~~~onPause ~~~ "+this); super.onPause(); } public void onStop() { Log.d("~~~~","~~~onStop ~~~ "+this); super.onPause(); } public void onDestroy() { Log.d("~~~~","~~~onDestroy ~~~ "+this); super.onDestroy(); } } 

main.xml

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:text="Start" android:onClick="onStartButton" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <Button android:text="Stop" android:onClick="onStopButton" android:layout_width="fill_parent" android:layout_height="wrap_content"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> </LinearLayout> 

AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xyz" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".AsyncTaskTestActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MagicAppRestart"/> </application> </manifest> 

और लॉग का एक प्रासंगिक हिस्सा (ध्यान दें कि केवल onPause कहलाता है ):

 D/~~~~ (13667): ~~~onStartButton { D/~~~~ (13667): ~~~onStartButton } D/~~~~ (13667): ~~~doInBackground started D/~~~~ (13667): ~~~sleep#0 D/~~~~ (13667): ~~~sleep#1 D/~~~~ (13667): ~~~sleep#2 D/~~~~ (13667): ~~~sleep#3 D/~~~~ (13667): ~~~sleep#4 D/~~~~ (13667): ~~~sleep#5 D/~~~~ (13667): ~~~sleep#6 D/~~~~ (13667): ~~~sleep#7 D/~~~~ (13667): ~~~sleep#8 D/~~~~ (13667): ~~~sleep#9 D/~~~~ (13667): ~~~sleeping over D/~~~~ (13667): ~~~doInBackground ended D/~~~~ (13667): D/~~~~ (13667): D/~~~~ (13667): ~~~taskDone ~~~ com.xyz.AsyncTaskTestActivity@40516988 D/~~~~ (13667): D/~~~~ (13667): ~~~onStartButton { D/~~~~ (13667): ~~~onStartButton } D/~~~~ (13667): ~~~doInBackground started D/~~~~ (13667): ~~~sleep#0 D/~~~~ (13667): ~~~sleep#1 D/~~~~ (13667): ~~~sleep#2 D/~~~~ (13667): ~~~sleep#3 D/~~~~ (13667): ~~~sleep#4 D/~~~~ (13667): ~~~sleep#5 D/~~~~ (13667): ~~~onStopButton { I/ActivityManager( 81): Starting: Intent { cmp=com.xyz/.MagicAppRestart } from pid 13667 D/~~~~ (13667): ~~~onStopButton } D/~~~~ (13667): ~~~onPause ~~~ com.xyz.AsyncTaskTestActivity@40516988 I/ActivityManager( 81): Process com.xyz (pid 13667) has died. I/WindowManager( 81): WIN DEATH: Window{4073ceb8 com.xyz/com.xyz.AsyncTaskTestActivity paused=false} I/ActivityManager( 81): Start proc com.xyz for activity com.xyz/.AsyncTaskTestActivity: pid=13698 uid=10101 gids={} I/ActivityManager( 81): Displayed com.xyz/.AsyncTaskTestActivity: +44ms (total +65ms) D/~~~~ (13698): ~~~onCreate ~~~ com.xyz.AsyncTaskTestActivity@40517238