AsyncTask बनाम RX - एक छोटे से उपयोग के मामले में

हाल ही में मैं एक ऐसे कार्य पर काम कर रहा था जहाँ मुझे क्रमबद्ध तरीके से 12 नेटवर्क अनुरोधों को सिंक्रनाइज़ करने की आवश्यकता थी। RESTful JSON एपि अनुरोध, एक के बाद एक।

मैं विशेष रूप से एक कैमरे से विकल्पों का अनुरोध करने पर काम कर रहा था, जिसने एक स्थानीय एपीआई की मेजबानी की जिसके साथ आपका एंड्रॉइड डिवाइस वाईफाई पर कनेक्ट हो सकता है। एपीआई वापस आ जाएगा जो विकल्प उपलब्ध थे, और उन विकल्पों में से प्रत्येक के लिए कौन से मूल्य चुने जा सकते हैं।

एक लचीला एपीआई, इसने आपको एक ही अनुरोध के साथ एक ही समय में कई विकल्पों की उपलब्धता को क्वेरी करने की अनुमति दी। मेरे पास 12 विकल्प थे जिनमें मुझे दिलचस्पी थी, एक्सपोज़र सेटिंग्स और एपर्चर, और जैसे विकल्प।

एकमात्र समस्या यह थी, यदि कोई विकल्प उपलब्ध नहीं था, तो कैमरे का एपीआई 404 प्रतिसाद के रूप में वापस आ जाता था। और, जब मैंने कई अनुरोध किए! इसलिए यदि 12 में से सिर्फ एक विकल्प गायब था, तो आपको 404 नहीं मिला और अन्य 11. के बारे में कुछ भी नहीं पता था। ठीक है कि यह बेकार है, मुझे प्रत्येक विकल्प का अनुरोध करने के लिए स्विच करना पड़ा, एक बार में।

मैं उन विकल्पों में से प्रत्येक को ले रहा था और एक स्पिनर के माध्यम से उपयोगकर्ता को अपनी सेटिंग्स चुनने के लिए एक पुनर्नवीनीकरण दृश्य में डाल रहा था।

जिन ऐप्स में मैंने काम किया है, उनमें मैंने विशेष रूप से RXJava2 से पहले RX का उपयोग किया है। लेकिन मुझे उद्यम डेस्क जॉब में अभी तक सहयोग करने के लिए इसे अपने दिन में इस्तेमाल करने का अवसर नहीं मिला था।

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

मैं शायद अभी तक विचारों को बेचने में सबसे अच्छा नहीं हूं, लेकिन मैं सुधार करने की कोशिश कर रहा हूं!

अच्छी तरह से यहाँ मेरे पास एक आदर्श उदाहरण है जहाँ आरएक्स होने से ये 12 अनुरोध मेरे लिए आसान और अधिक बनाए रखने योग्य होंगे।

हम आम तौर पर अपने बैकग्राउंड वर्क के लिए AsyncTasks का उपयोग कर रहे थे, जैसा कि इस ऐप में लंबे समय से किया गया है। विरासत में एक जीवनकाल होता है, एक बार जब आप एक तकनीक पर निर्णय लेते हैं तो यह थोड़ी देर के लिए उस एप्लिकेशन का पालन करेगा। एक और कारण है कि शोध के निर्णय हल्के ढंग से नहीं किए जाते हैं।

मुझे, मैं नई चीजों की कोशिश कर रहा हूं, और अत्याधुनिक रहना पसंद करता हूं।

इससे भी बेहतर यह है कि मुझे उस बिंदु पर क्या मिला, जहां मैं वास्तव में आरएक्स और एसिंक्सटैस्क की तुलना और उदाहरण कर सकता हूं, यह तथ्य था कि एक 3 पार्टी लाइब्रेरी जो हम उपयोग कर रहे थे, आरएक्सजैवा संस्करण 1 पर निर्भरता थी।

इस समय कम और निहारना, वहाँ यह हमारे कोड बेस में बैठे थे उपयोग किए जाने के इंतजार में।

इसलिए, मैं और मेरे सह-कर्मचारियों की मंजूरी ने RX और AsyncTask का उपयोग करने के बीच इस एक कार्य के अंतर का परीक्षण करने के लिए बेंचमार्क करने के लिए निर्धारित किया है।

समय बिल्कुल नगण्य है! उम्मीद है कि यह किसी भी मिथक को दूर करता है जो छोटे पृष्ठभूमि कार्यों के लिए, AsyncTask का उपयोग धीमा है। मुझे यह कई स्रोतों से नियमित रूप से बताया जाता है। मुझे आश्चर्य है कि अगर मैंने बड़े परीक्षण किए तो मुझे क्या मिलेगा।

मैंने एक छोटा सा नमूना सेट किया। 6 बार दोनों समाधानों के साथ अपनी गतिविधि चलाना और मुझे यही मिला:

RX:
11–17 08: 59: 00.086 12 RX अनुरोध विकल्प के लिए समाप्त हो गए: 3863ms
११-१ Requests ० Requests: ५ ९: २०.०१ 12 १२ आरएक्स अनुरोध विकल्प के लिए समाप्त हुए: ३ .१६ मी
11–17 08: 59: 39.143 12 आरएक्स अनुरोध विकल्प के लिए समाप्त हुए: 3628ms
11–17 08: 59: 57.367 12 RX अनुरोध विकल्प के लिए समाप्त हुए: 3561ms
11–17 09: 00: 15.758 12 RX अनुरोध विकल्प के लिए समाप्त हो गए: 3713ms
11–17 09: 00: 39.129 12 RX अनुरोध विकल्प के लिए समाप्त हो गए: 3612ms

मेरे RX समाधान के लिए औसत रनटाइम 3698.83ms।

ATAsync:
११-१ finished ०77: ५४: ४ ९ .२ 12 १२ विकल्प के लिए समाप्त हुए अनुरोध: ४० .५ कि.मी.
11–17 08: 55: 37.718 12 विकल्प के लिए समाप्त हुए अनुरोध: 3980ms
11–17 08: 55: 59.819 12 विकल्प के लिए अनुरोध समाप्त: 3925 मी
11–17 08: 56: 20.861 12 विकल्प के लिए समाप्त हुए अनुरोध: 3736ms
11–17 08: 56: 41.438 12 विकल्प के लिए समाप्त हुए अनुरोध: 3549ms
11–17 08: 57: 01.110 12 विकल्प के लिए अनुरोध समाप्त: 3833 मी

मेरे AsyncTask समाधान के लिए औसत रनटाइम 3851.33ms।

आरएक्स का उपयोग करने से मेरी राय में रनटाइम्स में कोई अंतर नहीं है। वास्तव में जो रनटाइम बनाता है वह उस बैकग्राउंड कार्य के अंदर का ऑपरेशन है जिसे आप गणना करने की कोशिश कर रहे हैं।

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

हालांकि अभी भी AsyncTasks का उपयोग करना ठीक है और हर कोई वही कर सकता है जो वे आमतौर पर करते हैं, RX शुरू करने से केवल पृष्ठभूमि कार्यों से परे चला जाता है। आपको नए अवसरों और शक्तिशाली तरीकों की एक दुनिया मिलती है जो आप अपने वर्कफ़्लो और संचालन को कार्यात्मक रूप से पाइप कर सकते हैं। आरएक्स के साथ कई ऐसी चीजें हैं जो आप AysncTasks से नहीं कर सकते।

बस अपने AsyncTask वर्जन को काम करने के लिए मुझे जो अतिरिक्त काम करने की जरूरत है, उसे देखें। मैंने किसी कंपनी को संवेदनशील नहीं दिखाने के लिए कोड को बाधित किया है यह मेरे वास्तविक कोड का मजाक है।

AsyncTask संस्करण:

सार्वजनिक वर्ग के विकल्पCameraRequester कार्यान्वयन IOptionRepository {
    ATAsyncTask currentTask;
    बूलियन कैन्सेलड है;
    अंतिम HttpConnector कनेक्टर;
    निजी लंबी शुरुआत;
    सार्वजनिक विकल्पCameraRequester (स्ट्रिंग ipAddress) {
        this.connector = new HttpConnector (ipAddress);
    }
    सार्वजनिक शून्य रद्द () {
        isCanceled = true;
        अगर (currentTask! = null) {
            currentTask.cancel (सही);
            currentTask = null;
        }
    }
    सार्वजनिक शून्य getOptions (कॉलबैक कॉलबैक) {
        अगर (iscanceled) वापसी;
        startTime = System.currentTimeMillis ();
        Log.i (MyLog.TAG, "विकल्पों के लिए अनुरोध शुरू");
        इटरेटर  इटरेटर =
            CameraOption.getAllPossibleOptions () इटरेटर ()।;
        requestOption (पुनरावृत्ति, कॉलबैक);
    }
    शून्य अनुरोध करना (अंतिम Iterator  पुनरावृत्ति,
                       अंतिम कॉलबैक कॉलबैक) {
        अगर (iterator.hasNext ()) {
            अंतिम लंबे समय = System.currentTimeMillis ();
            Log.i (MyLog.TAG, "विकल्प के लिए अनुरोध समाप्त:" +
                    (System.currentTimeMillis () - startTime) +
                    "सुश्री");
            वापसी;
        }
        अंतिम CameraOption विकल्प = iterator.next ();
        अंतिम AsyncTask <शून्य, शून्य, कैमराऑक्शन> कार्य =
                नया AsyncTask <शून्य, शून्य, कैमराऑक्शन> () {
                    CameraOption doInBackground (V ..) {
                        JSONObject परिणाम =
                            connector.getOption (option.getName ());
                        अगर (परिणाम == अशक्त) {
                            वापसी;
                        } अन्य {
                            // JSONObject के साथ कुछ काम करें
                        }
                        वापसी का विकल्प;
                    }
                    शून्य onPostExecute (CameraOption विकल्प) {
                        OptionsCameraRequester.this.currentTask =
                            शून्य;
                        अगर (विकल्प! = अशक्त) {
                            callback.onOptionAvailable (विकल्प);
                        }
                        यदि (isCanceled) {
                            requestOption (पुनरावृत्त, कॉलबैक);
                        }
                    }
                };
        task.execute ();
        currentTask = task;
    }
}

RX संस्करण:

सार्वजनिक वर्ग के विकल्पCameraRequester कार्यान्वयन IOptionRepository {
    अंतिम HttpConnector कनेक्टर;
    सदस्यता getOptionsSubscription;
    सार्वजनिक विकल्पCameraRequester (स्ट्रिंग ipAddress) {
        this.connector = new HttpConnector (ipAddress);
    }
    सार्वजनिक शून्य रद्द () {
        अगर (getOptionsSubscription! = null) {
            getOptionsSubscription.unsubscribe ();
            getOptionsSubscription = अशक्त;
        }
    }
    // मैं कॉलबैक का उपयोग करता हूं ताकि मैं उसी प्रणाली का पालन कर सकूं
    // इंटरफ़ेस और केवल इस के लिए निहित आरएक्स कोड रखें
    // कक्षा।

    सार्वजनिक शून्य getOptions (अंतिम कॉलबैक कॉलबैक) {
        अंतिम लंबे समय = System.currentTimeMillis ();
        Log.i (MyLog.TAG, "विकल्प के लिए आरएक्स अनुरोध शुरू हुआ");
        getOptionsSubscription =
        Observable.from (CameraOption.getAllPossibleOptions ())
            // कैमरे से प्रत्येक विकल्प का अनुरोध करें
            .map (नया Func1  () {
                    
                सार्वजनिक CameraOption कॉल (CameraOption विकल्प) {
                    JSONObject ऑब्जेक्ट =
                        connector.getOption (option.getName ());
                    अगर (वस्तु == अशक्त) {
                        cameraOption.setAvailable (गलत);
                    } अन्य {
                        // JSONObject के साथ init विकल्प पर काम करें
                    }
                    कैमरा वापसी;
               }
            })
            // ऐसे विकल्पों को फ़िल्टर करें जो समर्थित नहीं हैं
            .filter (नया Func1  () {
                    
                सार्वजनिक बूलियन कॉल (CameraOption कैमराऑप्शन) {
                    वापसी कैमरा
                }
            })
            // डिक्लेयर थ्रेड्स का काम किया जाता है और उसे प्राप्त किया जाता है
            .observeOn (AndroidSchedulers.mainThread ())
            .subscribeOn (Schedulers.newThread ())
            // तैयार होने के बाद प्रत्येक विकल्प को पास करें
            .subscribe (नया सब्सक्राइबर  () {
         
                सार्वजनिक शून्य चालू () {
                   getOptionsSubscription = अशक्त;
                   Log.i (MyLog.TAG, "RX अनुरोध समाप्त:" +
                        (System.currentTimeMillis () - समय) + "ms");
                }
                सार्वजनिक शून्य onError (फेंकने योग्य ई) {
                   MyLog.eLogErrorAndReport (MyLog.TAG, e);
                   callback.onError ();
                }
                सार्वजनिक शून्य onNext (CameraOption कैमराऑप्शन) {
                    callback.onOptionAvailable (cameraOption);
                }
           });
    }
}

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