multithreading - كيف يمكنني تشغيل الكود على مؤشر ترابط الخلفية على نظام Android؟



(5)

class Background implements Runnable {
    private CountDownLatch latch = new CountDownLatch(1);
    private  Handler handler;

    Background() {
        Thread thread = new Thread(this);
        thread.start();
        try {
            latch.await();
        } catch (InterruptedException e) {
           /// e.printStackTrace();
        }
    }

    @Override
    public void run() {
        Looper.prepare();
        handler = new Handler();
        latch.countDown();
        Looper.loop();
    }

    public Handler getHandler() {
        return handler;
    }
}

أريد تشغيل بعض التعليمات البرمجية في الخلفية باستمرار. لا أريد أن أفعل ذلك في الخدمة. هل هناك أي طريقة أخرى ممكنة؟

لقد حاولت استدعاء فئة مؤشر Thread في نشاطي ولكن يبقى نشاطي في الخلفية لبعض الوقت ثم يتوقف. فئة مؤشر Thread أيضاً يتوقف عن العمل.

class testThread implements Runnable 
    {
        @Override
        public void run() 
        {
            File file = new File(Environment.getExternalStorageDirectory(),"/BPCLTracker/gpsdata.txt");
            int i=0;

        RandomAccessFile in = null;

        try
        {
            in = new RandomAccessFile(file, "rw");


        } 
        catch (FileNotFoundException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //String line =null;
        while (true) 
        {
            HttpEntity entity=null;
            try 
            {
                if (isInternetOn()) 
                {
                        while ((line = in.readLine()) != null)
                        {

                            HttpClient client = new DefaultHttpClient();
                            String url = "some url";
                            HttpPost request = new HttpPost(url);
                            StringEntity se = new StringEntity(line);
                            se.setContentEncoding("UTF-8");
                            se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
                            entity = se;
                            request.setEntity(entity);
                            HttpResponse response = client.execute(request);
                            entity = response.getEntity();
                            i++;
                        }
                        if((line = in.readLine()) == null && entity!=null)
                        {
                            file.delete();
                            testThread t = new testThread();
                            Thread t1 = new Thread(t);
                            t1.start();
                        }


                }// end of if
                else
                {
                    Thread.sleep(60000);

                } // end of else
            }// end of try
            catch (NullPointerException e1)
            {
                e1.printStackTrace();
            } 
            catch (InterruptedException e2) 
            {
                e2.printStackTrace();
            }
            catch (IOException e1) 
            {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }// end of while
    }// end of run

أريد تشغيل بعض التعليمات البرمجية في الخلفية باستمرار. لا أريد أن أفعل ذلك في الخدمة. هل هناك أي طريقة أخرى ممكنة؟

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

إذا كنت لا تعرف كيف تبدأ هنا هو تعليمي جيد:

ملاحظة: أيضا هناك إمكانية لاستخدام IntentService مع ResultReceiver الذي يعمل كذلك.


بالنسبة لعمليات الخلفية على المدى الطويل ، فإن المواضيع غير مناسبة مع Android. ومع ذلك ، هنا هو رمز والقيام بذلك على مسؤوليتك الخاصة ...

تذكر أن الخدمة أو الموضوع سيتم تشغيله في الخلفية ولكن مهمتنا تحتاج إلى جعل المشغل (الاتصال مرة أخرى ومرة ​​أخرى) للحصول على التحديثات ، أي بمجرد اكتمال المهمة ، نحتاج إلى استدعاء الوظيفة للتحديث التالي.

الموقت (المشغل الدوري) ، التنبيه (مشغل قاعدة الوقت) ، البث (مشغل قاعدة الحدث) ، سوف يوقظ العودية وظائفنا.

public static boolean isRecursionEnable = true;

void runInBackground() {
    if (isRecursionEnable)
        return;    // Handle not to start multiple parallel threads

    // isRecursionEnable = false; when u want to stop
    // on exception on thread make it true again  
    new Thread(new Runnable() {
        @Override
        public void run() {
            // DO your work here
            // get the data
            if (activity_is_not_in_background) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        //uddate UI
                        runInBackground();
                    }
                });
            } else {
                runInBackground();
            }
        }
    }).start();
}

بديل ل AsyncTask هو robospice. https://github.com/octo-online/robospice .

بعض ميزات robospice.

1.يتم تنفيذ طلبات الشبكة بشكل غير متزامن (في الخلفية AndroidService) (على سبيل المثال: طلبات REST باستخدام Spring Android). يخطر لك التطبيق ، على مؤشر ترابط واجهة المستخدم ، عندما تكون النتيجة جاهزة.

2. انها كتبت بقوة! يمكنك تقديم طلباتك باستخدام POJOs وتحصل على POJOs حسب نتائج الطلب.

3. لا تفرض أي قيود على POJOs المستخدمة للطلبات ولا على فئات النشاط التي تستخدمها في مشاريعك.

4.caches النتائج (في Json مع كل من جاكسون و Gson ، أو Xml ، أو ملفات نصية مسطحة ، أو الملفات الثنائية ، حتى باستخدام ORM Lite).

5. قم بإبلاغ نشاطاتك (أو أي سياق آخر) عن نتيجة طلب الشبكة إذا وفقط إذا كانت لا تزال على قيد الحياة

لا يؤدي تسرب الذاكرة على الإطلاق ، مثل Android Loaders ، على عكس Android AsyncTasks ، إلى الإبلاغ عن أنشطتك على مؤشر ترابط واجهة المستخدم.

7. يستخدم نموذج التعامل مع استثناء بسيط ولكن قوي.

عينات لتبدأ. https://github.com/octo-online/RoboSpice-samples .

عينة من robospice على https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result .


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

كتابة رمز متعدد مؤشرات للاختبار

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

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

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

اختبارات وحدة الكتابة لرمز متعددة الخيوط

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

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

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

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





android multithreading