سؤال

هذا السؤال لديه بالفعل إجابة هنا:

أواجه مشكلة في فئة Asynctask. يبدو أن مهمتي تتوقف عن العمل بعد إنشاء 4 أو 5 مهام.

أنا أعاني من نشاطين. النشاط الرئيسي الذي يحمل فقط زر يبدأ نشاطًا ثانيًا يسمى ImageActivity.

الخيال بسيط للغاية. لقد حصلت على oncreate التي تحدد التصميم ، ثم تبدأ مجموعة Asynctash جديدة تقوم بتحميل صورة من الإنترنت. هذا يعمل بشكل جيد في المرات القليلة الأولى. ولكن مما يتوقف فجأة عن العمل. يتم تشغيل طريقة OnPreexecute في كل مرة ، ولكن ليس طريقة Doinbackground. لقد حاولت تبسيط Goinbackground مع حلقة نوم ، ويحدث نفس الشيء. لا أستطيع أن أفهم هذا السلوك لأن Asynctask يتم إلغاؤه وتعيينه على كل شيء في طريقة OnDestroy. لذلك في كل مرة أبدأ فيها خيالًا جديدًا ، أقوم أيضًا بإنشاء مسجلة غير متصلة جديدة.

أقوم بإعادة إنشاء المهم والمهمة عن طريق الضغط على زر العودة ، ومن النقر فوق الزر على النشاط الرئيسي.

أي أفكار أي شخص؟ أنا حقًا أعاني من هذا.

تحديث: الرمز الذي يبدأ التصور (داخل زر OnClickListener)

Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.setClassName(this, ImageActivity.class.getName());
startActivity(intent);

الرمز أعلاه يبدأ هذا النشاط

    public class ImageActivity extends Activity {

    private AsyncTask<Void, Void, Void> task;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        task = new AsyncTask<Void, Void, Void>() {

            @Override
            protected void onPreExecute()
            {
                Log.d(TAG, "onPreExecute()");
            }

            @Override
            protected Void doInBackground(Void... params)
            {
                Log.d(TAG, "doInBackground() -- Here is the download");
                // downloadBitmap("http://mydomain.com/image.jpg")
                return null;
            }

            @Override
            protected void onPostExecute(Void res)
            {
                Log.d(TAG, "onPostExecute()");
                if(isCancelled()){
                    return;
                }
            }
        }.execute();
    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        task.cancel(true);
    }
}

تحديث:

لقد اختبرت استخدام مجموعة من الخيوط التقليدية وطريقة RunonuithRead ، ويبدو أنها تعمل بشكل أفضل. الآن يعمل الخيط في كل مرة.

هل كانت مفيدة؟

المحلول

إزالة المقاوم غير المتبعة واستخدام أ الموضوع التقليدي بدلا من الجمع بينه مع Runonuithread يبدو أنه يعمل. لكنني ما زلت لم أجد السبب وراء عدم استقرار المراهن.

هنا هو الرمز الذي يعمل بالنسبة لي:

public class ImageActivity extends Activity {

    private Thread worker;

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.main);

        worker = new Thread(new Runnable(){

            private void updateUI(final List<Object> list)
            {
                if(worker.isInterrupted()){
                    return;
                }
                runOnUiThread(new Runnable(){

                    @Override
                    public void run()
                    {
                        // Update view and remove loading spinner etc...
                    }
                });
            }

            private List<Object> download()
            {
                // Simulate download
                SystemClock.sleep(1000);
                return new ArrayList<Object>();
            }

            @Override
            public void run()
            {
                Log.d(TAG, "Thread run()");
                updateUI(download());
            }

        });
        worker.start(); }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        worker.interrupt();
    }
}

نصائح أخرى

واجهت مشكلة مماثلة. لا يمكن أن يكون لديك العديد من المخططات المتزامنة تعمل بشكل متوازٍ حتى SDK 11. تحقق هنا لمزيد من المعلومات

لقد واجهت هذه المشكلة أيضًا. كما ترى AsyncTask.execute, ، يتم تشغيل مهمتك على قائمة انتظار متسلسلة (من مصدر Android 4.3):

عند تقديمها لأول مرة ، تم تنفيذ المخالفات المتسلسلة بشكل تسلسلي على خيط خلفية واحد. بدءًا من الدونات ، تم تغيير هذا إلى مجموعة من الخيوط مما يسمح بمهام متعددة بالعمل بالتوازي. بدءًا من قرص العسل ، يتم تنفيذ المهام على موضوع واحد لتجنب أخطاء التطبيق الشائعة الناتجة عن التنفيذ المتوازي.

هذا يتفق مع السلوك الذي رأيته. كان لي ل AsyncTask برزت حوار في doInBackground وحظره حتى تم إغلاق الحوار. الحوار يحتاج إلى خاص به AsyncTask لإكمال. مربع الحوار AsyncTask.doInBackground الطريقة لم تنفذ أبدًا لأن الأصل AsyncTask كان لا يزال محظورا.

الحل هو تنفيذ الثاني AsyncTask في منفصلة Executor.

استخدم TraceView للتحقيق - أو الحصول على تفريغ مؤشر ترابط. أظن أن أحد خيوط Asynctask الخاصة بك معلقة على التنزيل.

يحتوي Asynctask على تجمع خيوط صغير ، لذلك إذا كانت إحدى مهامك معلقة ، فقد ينتهي الأمر بحظر تجمع الخيوط الخاص بك.

إليك اختبارًا سريعًا يمكنك تشغيله - في 4.3 ، أرى أن لديّ 5 خيوط متزامنة فقط يمكنني تشغيلها. عندما يخرج موضوع واحد ، تبدأ المواضيع الأخرى.

  private void testAsyncTasks() {

        for (int i = 1; i <= 10; i++) {
              final int tid = i;
              new AsyncTask<Integer, Void, Void>() {
                    protected void onPreExecute() {
                          Log.d("ASYNCTASK", "Pre execute for task : " + tid);
                    };

                    @Override
                    protected Void doInBackground(Integer... args) {
                          int taskid = args[0];
                          long started = SystemClock.elapsedRealtime();
                          Log.d("ASYNCTASK", "Executing task: " + taskid + " at " + started);
                          for (int j = 1; j <= 20; j++) {
                                Log.d("ASYNCTASK", "   task " + taskid + ", time=" + (SystemClock.elapsedRealtime() - started));
                                SystemClock.sleep(1000);
                          }
                          return null;
                    }

                    protected void onPostExecute(Void result) {
                          Log.d("ASYNCTASK", "Post execute for task : " + tid);
                    };
              }.execute(i);

        }
  }

لا يجب أن تقلق بشأن مؤشر ترابط التدبير المنزلي في Android لأنه يديره النظام.

يرجى أيضًا نشر طريقة تنزيل الصورة. هل حاولت أيضًا عدم إلغاء الخيط في طريقة OnDestroy ()؟ كيف تقوم بإرجاع الصورة إلى موضوع واجهة المستخدم؟

المشكلة التي أعتقد أنها مع مهمة تنزيل الصورة الثقيلة. حتى إذا قمت بإلغاء مهمة ASYNC ، فسيستمر تنزيل الصورة في التنفيذ ولا تنتهي مهمة ASYNC حتى يكتمل التنزيل. قد ترغب في التحقق من طريقة iScancelled () على Aynctask أثناء تشغيل التنزيل وقتل التنزيل إذا تم إلغاء المهمة.

للرجوع إليها ، Heres الوثائق على طريقة الإلغاء ():محاولات إلغاء تنفيذ هذه المهمة. ستفشل هذه المحاولة في حالة الانتهاء من المهمة بالفعل ، أو تم إلغاؤها بالفعل ، أو لا يمكن إلغاؤها لسبب آخر. إذا نجحت ، ولم تبدأ هذه المهمة عند استدعاء الإلغاء ، يجب ألا يتم تشغيل هذه المهمة أبدًا. إذا كانت المهمة قد بدأت بالفعل ، فإن معلمة MayinTrupruptifrunning تحدد ما إذا كان ينبغي مقاطعة مؤشر الترابط الذي ينفذ هذه المهمة في محاولة لإيقاف المهمة. ستؤدي استدعاء هذه الطريقة إلى استدعاء (كائن) مُحسّن على مؤشر ترابط واجهة المستخدم بعد عودة doinbackground (Object []). يضمن استدعاء هذه الطريقة أن onpostexecute (كائن) لم يتم الاحتجاج به أبدًا. بعد استدعاء هذه الطريقة ، يجب عليك التحقق من القيمة التي يتم إرجاعها بواسطة Iscancelled () بشكل دوري من DoInbackground (Object []) لإنهاء المهمة في أقرب وقت ممكن.

كان لدي هذا أيضًا ، لا يوجد سبب حقيقي لعدم البدء. لقد لاحظت أنه بعد إعادة تشغيل ADB لقد نجح مرة أخرى. لست متأكدًا لماذا هذا ، لكنه نجح بالنسبة لي

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top