ऑब्जेक्ट को क्रमबद्ध करने के बजाय पार्सलबल का उपयोग करने का लाभ


97

जैसा कि मैं समझता हूं, Bundleऔर Parcelableजिस तरह से एंड्रॉइड में क्रमांकन करता है, उसका उपयोग किया जाता है। इसका उपयोग गतिविधियों के बीच डेटा पारित करने में उदाहरण के लिए किया जाता है। लेकिन मुझे आश्चर्य है, अगर Parcelableउदाहरण के लिए मेरी व्यावसायिक वस्तुओं की आंतरिक स्थिति को बचाने के मामले में क्लासिक क्रमांकन के बजाय उपयोग करने में कोई लाभ है ? क्या यह क्लासिक तरीके से सरल या तेज होगा? मुझे क्लासिक क्रमांकन का उपयोग कहां करना चाहिए और बंडलों का उपयोग करने के लिए बेहतर कहां है?

जवाबों:


99

"प्रो Android 2" से

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

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


9
"प्रो एंड्रॉइड 2" क्या है?
एलिकएल्ज़िन-किलाका

79
दूसरा पैराग्राफ सच नहीं है, आप बंडल का उपयोग करके एक पार्सल को एक गतिविधि के पैरामीटर के रूप में पास कर सकते हैं ...
Ixx

3
जब मैं अपनी वस्तुओं को अनुक्रमित करता हूं तो मैं एक getBundleविधि बनाता हूं , फिर उस writeToParcelरूप में कॉल करें dest.writeBundle(getBundle());और मेरे पास ऑब्जेक्ट में स्वचालित रूप से दोनों विकल्प उपलब्ध हैं। यहां पर दी गई जीवित वस्तुओं के लिए दिलचस्प पार्सल सुविधाएँ हैं: developer.android.com/reference/android/os/Parcel.html
mikebabcock

2
@ एलएक्स: मैं सोच रहा था कि किसी को गतिविधि के लिए बंडल के माध्यम से एक पार्सल योग्य वस्तु को पारित करने की आवश्यकता क्यों होगी। IMO यदि आप ऐसा करते हैं तो आप क्रमिक रूप से एक और स्तर जोड़ रहे हैं अनावश्यक रूप से और कुछ नहीं।
राइज

4
फिलिप ब्रील ने इस बारे में एक अच्छा लेख बनाया, और एक प्रदर्शन परीक्षण भी जोड़ा। developerphil.com/parcelable-vs-serializable
WonderCsabo

23

Serializableएंड्रॉइड पर कॉमेटिकली धीमा है। सीमा कई मामलों में वास्तव में बेकार।

Parcelऔर Parcelableकाल्पनिक रूप से त्वरित हैं, लेकिन इसका दस्तावेज़ीकरण कहता है कि आपको इसे स्टोरेज करने के लिए सामान्य प्रयोजन के क्रमांकन के लिए उपयोग नहीं करना चाहिए, क्योंकि कार्यान्वयन एंड्रॉइड के विभिन्न संस्करणों के साथ भिन्न होता है (यानी एक ओएस अपडेट एक ऐप को तोड़ सकता है जो इस पर भरोसा करता है)।

उचित गति से स्टोरेज करने के लिए डेटा को क्रमबद्ध करने की समस्या का सबसे अच्छा समाधान अपने स्वयं के रोल करना है। मैं व्यक्तिगत रूप से अपनी स्वयं की उपयोगिता वर्गों में से एक का उपयोग करता हूं जिसमें समान इंटरफ़ेस है Parcelऔर जो सभी मानक प्रकारों को बहुत कुशलता से (प्रकार की सुरक्षा की कीमत पर) अनुक्रमित कर सकता है। यहाँ इसका संक्षिप्त संस्करण है:

public interface Packageable {
    public void readFromPackage(PackageInputStream in)  throws IOException ;
    public void writeToPackage(PackageOutputStream out)  throws IOException ; 
}


public final class PackageInputStream {

    private DataInputStream input;

    public PackageInputStream(InputStream in) {
        input = new DataInputStream(new BufferedInputStream(in));
    }

    public void close() throws IOException {
        if (input != null) {
            input.close();
            input = null;
        }       
    }

    // Primitives
    public final int readInt() throws IOException {
        return input.readInt();
    }
    public final long readLong() throws IOException {
        return input.readLong();
    }
    public final long[] readLongArray() throws IOException {
        int c = input.readInt();
        if (c == -1) {
            return null;
        }
        long[] a = new long[c];
        for (int i=0 ; i<c ; i++) {
            a[i] = input.readLong();
        }
        return a;
    }

...

    public final String readString()  throws IOException {
        return input.readUTF();
    }
    public final <T extends Packageable> ArrayList<T> readPackageableList(Class<T> clazz) throws IOException {
        int N = readInt();
        if (N == -1) {
            return null;
        }
        ArrayList<T> list = new ArrayList<T>();
        while (N>0) {
            try {
                T item = (T) clazz.newInstance();
                item.readFromPackage(this);
                list.add(item);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            N--;
        }
        return list;
    }

}



public final class PackageOutputStream {

    private DataOutputStream output;

    public PackageOutputStream(OutputStream out) {
        output = new DataOutputStream(new BufferedOutputStream(out));
    }

    public void close() throws IOException {
        if (output != null) {
            output.close();
            output = null;
        }
    }

    // Primitives
    public final void writeInt(int val) throws IOException {
        output.writeInt(val);
    }
    public final void writeLong(long val) throws IOException {
        output.writeLong(val);
    }
    public final void writeLongArray(long[] val) throws IOException {
        if (val == null) {
            writeInt(-1);
            return;
        }
        writeInt(val.length);
        for (int i=0 ; i<val.length ; i++) {
            output.writeLong(val[i]);
        }
    }

    public final void writeFloat(float val) throws IOException {
        output.writeFloat(val);
    }
    public final void writeDouble(double val) throws IOException {
        output.writeDouble(val);
    }
    public final void writeString(String val) throws IOException {
        if (val == null) {
            output.writeUTF("");
            return;
        }
        output.writeUTF(val);
    }

    public final <T extends Packageable> void writePackageableList(ArrayList<T> val) throws IOException {
        if (val == null) {
            writeInt(-1);
            return;
        }
        int N = val.size();
        int i=0;
        writeInt(N);
        while (i < N) {
            Packageable item = val.get(i);
            item.writeToPackage(this);
            i++;
        }
    }

}

2
आप के इस कस्टम वर्ग का उपयोग करने और केवल बाहरी इंटरफ़ेस लागू करने और समान कार्य करने में क्या अंतर है?
कारटोमन 42

1
बंडल फ़ील्ड नामों को क्रमबद्ध करता है ... यह हजारों ऑब्जेक्ट्स के लिए उपयुक्त नहीं है।
रूबेन स्क्रैटन

1
क्षमा करें, अभी तक एक और धारावाहिक का आविष्कार करना बेकार है - अब इससे निपटने के लिए सिर्फ एक और "पार्सल" है। एक पुस्तकालय के साथ चुनने के लिए बहुत सारे हैं (अंतर यह है कि लाइब्रेरी को वैट किया गया है, परीक्षण किया गया है, और एक प्रारूप का उपयोग करता है जिसे अन्य लोग उपयोग करते हैं): प्रोटोकॉलबफर्स, जेन्सन, एक्सएमएल, आदि। यह शर्म की बात है कि एंड्रॉइड लाइब्रेरी वास्तव में इस संबंध में बेकार है। ।

2
मुझे नहीं लगता कि शुरुआती वाक्य अब और सच है (5 साल बाद इसे बनाया गया था)। मैं लंबे समय से बिना किसी मुद्दे के जावा क्रमांकन का उपयोग कर रहा हूं। इस विषय पर कुछ संभावित दिलचस्प बातें आप मेरे द्वारा लिखे गए ब्लॉग पोस्ट में पा सकते हैं। nemanjakovacevic.net/blog/english/2015/03/24/…
Nemanja Kovacevic

1
हां, यह वास्तव में ऐसा कोई मुद्दा नहीं है। मैंने कई वर्षों से सीरियलेबल (अनुकूलित रीडऑबजेक्ट / राइटऑबजेक्ट कार्यान्वयन के साथ) के अलावा और कुछ भी उपयोग नहीं किया है। वास्तव में मैंने कुछ ही दिनों पहले कुछ क्रमबद्ध वस्तुओं के हेक्स डंप को देखा था और संतुष्ट था कि यह बहुत बेकार नहीं था।
रूबेन स्क्रैटन


11

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

जब इसे ठीक से लागू किया जाता है तो यह पार्सलबल की गति से मेल खाता है और एंड्रॉइड और / या जावा प्लेटफॉर्म के विभिन्न संस्करणों के बीच संगतता के लिए भी जिम्मेदार है।

यह लेख चीजों को स्पष्ट कर सकता है:

Java में Serializable और Externalizable के बीच क्या अंतर है?

एक सिडेनोट पर, यह कई बेंचमार्क में सबसे तेज़ क्रमांकन तकनीक है, जिसमें क्रियो, एवरो, प्रोटोकॉल बफ़र्स और जैक्सन (json) को हराया गया है:

http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking


7

ऐसा लगता है कि आजकल अंतर इतना कम नहीं है, कम से कम तब नहीं जब आप इसे अपनी गतिविधियों के बीच चलाते हैं।

इस वेबसाइट पर दिखाए गए परीक्षणों के अनुसार , पार्सलबल नए उपकरणों (जैसे नेक्सस 10) पर लगभग 10 गुना तेज है, और पुराने वाले (जैसे इच्छा जेड) पर लगभग 17 तेज है

तो यह आप पर निर्भर है कि वह इसका मूल्य तय करे।

शायद अपेक्षाकृत छोटी और सरल कक्षाओं के लिए, सीरियल योग्य ठीक है, और बाकी के लिए, आपको पार्सलबल का उपयोग करना चाहिए


मुझे लगता है कि आप पैसे के बारे में कह रहे हैं कि अंतर कम हो रहा है। हालांकि मुझे पता चला कि मार्सिलेबल बाइट सरणी के आकार के संदर्भ में क्रमिक उपयोग करना बहुत अधिक कुशल हो सकता है और इससे TransactionTooLargeException से बचने में मदद मिल सकती है। मुझे इस (मेरा) ब्लॉग पोस्ट nemanjakovacevic.net/blog/english/2015/03/24/…/
Nemanja Kovacevic

ठीक है, आप केवल विशाल मेमोरी उपभोग करने वाली वस्तु को एक स्थिर चर पर रख सकते हैं, और जब आप इसे प्राप्त करते हैं (उदाहरण के लिए onCreate पर) इसे सही करने के लिए सेट करें। नुकसान यह है कि यह बहु-प्रक्रियाओं का समर्थन नहीं करता है, और यह इसे करने के लिए थोड़ा गंदा तरीका है। अगर आप एक बड़े बिटमैप को पास करना चाहते हैं तो आश्चर्य है।
Android डेवलपर

4

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

चूंकि एंड्रॉइड सबसे ज्यादा बाइंडर पर निर्भर करता है, यदि सभी नहीं, तो आईपीसी कार्य करता है, यह ज्यादातर जगहों पर पार्सल को लागू करने के लिए समझ में आता है, और विशेष रूप से फ्रेमवर्क में, क्योंकि यह किसी अन्य प्रक्रिया में एक वस्तु को पारित करने की अनुमति देता है यदि आपको आवश्यकता है। यह वस्तुओं को "परिवहनीय" बनाता है।

लेकिन अगर आपके पास एक गैर-एंड्रॉइड-विशिष्ट व्यावसायिक परत है, जो ऑब्जेक्ट स्टेट्स को बचाने के लिए बड़े पैमाने पर सीरीज़ेबल्स का उपयोग करते हैं, और केवल उन्हें फ़ाइल सिस्टम में संग्रहीत करने की आवश्यकता है, तो मुझे लगता है कि सीरियल करने योग्य ठीक है। यह पार्सलेबल बॉयलर-प्लेट कोड से बचने की अनुमति देता है।


आप किन उदाहरणों में Saya फ़ाइल सिस्टम में एक वास्तविक ऑब्जेक्ट स्टोर करना चाहते हैं? क्यों नहीं बस वस्तुओं को प्राप्त करें और वास्तविक सामग्री को एक फ़ाइल में संग्रहीत करें। उदाहरण के लिए JSON देखें या xml भी। आप JSON या XML प्रारूप में ऑब्जेक्ट्स को सहेज सकते हैं, POJO / इकाई प्रकारों में ऑब्जेक्ट्स जो कि ज्यादातर राज्यों और गेटर्स के साथ निर्मित एक विशिष्ट डेटा ऑब्जेक्ट का निर्माण करते हैं और उस राज्य के लिए बसते हैं। इस तरह उन वस्तुओं को संग्रहीत करने के उद्देश्य से वस्तुओं को क्रमबद्ध करने की कोई आवश्यकता नहीं है क्योंकि आप सभी वस्तुओं के बारे में परवाह करते हैं
जोनाथन

1

इस लेख के आधार पर http://www.mooproductions.org/node/6?page=5 पार्सलबल तेज होना चाहिए।

लेख में उल्लेख नहीं किया गया है, क्या मुझे लगता है कि धारावाहिक वस्तुएं दूरस्थ सेवाओं के लिए एआईडीएल में काम नहीं करेंगी।


1

मैं सिर्फ GSON -> सीरियल को JSON स्ट्रिंग का उपयोग करता हूं -> JSON स्ट्रिंग से ऑब्जेक्ट को पुनर्स्थापित करता हूं।


यह छोटी वस्तुओं के लिए ठीक है, इतना नहीं जब आपके पास प्रत्येक में बहुत सारे गुणों के साथ वस्तुओं के बड़े सरणियां होती हैं।
निकम्कोम्ब

0

इसके अलावा पार्सलबल कस्टम कार्यान्वयन प्रदान करता है जहां उपयोगकर्ता को राइटटॉपरसेल () को ओवरराइड करके अपनी प्रत्येक वस्तु को पार्सल करने का मौका मिलता है, हालांकि क्रमबद्धता इस कस्टम कार्यान्वयन को नहीं करती है क्योंकि डेटा पास करने के तरीके में जेएवीए प्रतिबिंब एपीआई शामिल है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.