android बहुत बड़े SOAP प्रतिक्रिया-एंड्रॉइड- मेमोरी त्रुटि से बाहर




android-ksoap2 (3)

बस एक अद्यतन, मुझे पता चला कि AndroidHttpTransport में "कॉल" विधि इस लाइन पर स्मृति से बाहर चल रही थी -

           if (debug) {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    byte[] buf = new byte[256];
                    while (true) {
                        int rd = is.read(buf, 0, 256);
                        if (rd == -1)
                            break;
                        bos.write(buf, 0, rd);
                    }
                    bos.flush();
                    buf = bos.toByteArray(); //Goes out of memory here
                    responseDump = new String(buf);
                    is.close();
                    is = new ByteArrayInputStream(buf);

बैटएरे को कॉल करने के लिए बहुत मेमोरी लेता है, इसलिए इस पर काबू पाने के लिए, बाइट सरणी पर प्रतिक्रिया बदलने के बजाय, मैं अब सीधे इसे एक XML फ़ाइल में लिखता हूं, और यह मेरी पसंद के स्थान पर सहेजा जाता है यहाँ -

if (debug) {
    FileOutputStream bos = new FileOutputStream("/data/data/com.mypackage.myapp/response.xml");
    byte[] buf = new byte[1048576];
    int current = 0; int i=0; int newCurrent = 0;
    while ((current = inputStream.read(buf)) != -1) {
        newCurrent = newCurrent + current;
    Log.d("current", "Current = " + current + " total = "+newCurrent+" i = "+i++);
                    bos.write(buf, 0, current);
                }
                bos.flush();
}

डिवाइस अब स्मृति से बाहर नहीं चलता है, और मेरे पास एक कस्टम पार्स विधि है जो इस XML को लेती है और इसे डीबी में लिखती है।

मेरे पास एक ऐसा आवेदन है जहां मुझे पहली बार चलाने के दौरान एक एसओएपी कॉल के जरिए एक जाससेवरी के लिए आवेदन में बड़ी मात्रा में डेटा डाउनलोड करना होगा प्रतिक्रिया तब एक समारोह में भेजी जाती है जो एक्सएमएल को परिवर्तित करती है और डेटा को डीबी फ़ाइल में स्टोर करती है।

डेटा 16 एमबी आकार से अधिक है और मेरे पास एक java.lang.OutOfMemoryError हर बार है।

कम मात्रा में डेटा देने के लिए webservice को संशोधित करना एक विकल्प नहीं है।

क्या बड़े डेटा को डाउनलोड करने में सक्षम होने का कोई तरीका है? शायद एक इंपुटस्ट्रीम की तरह कुछ है?

यह मेरा कोड है

public Protocol[] getProtocols() {

    String METHOD_NAME = "GetProtocols";
    String SOAP_ACTION = "urn:protocolpedia#GetProtocols";
    Log.d("service", "getProtocols");
    SoapObject response = invokeMethod(METHOD_NAME, SOAP_ACTION);
    return retrieveProtocolsFromSoap(response);
}

private SoapObject invokeMethod(String methodName, String soapAction) {
    Log.d(TAG, "invokeMethod");
    SoapObject request = GetSoapObject(methodName);
    SoapSerializationEnvelope envelope = getEnvelope(request);
    return makeCall(envelope, methodName, soapAction);

}

क्या कोई इस बात पर सुझाव दे सकता है कि इस मामले में क्या किया जाना चाहिए?

धन्यवाद और मुकुल के संबंध में


फिक्स्ड!

मैंने यहां से एचटीटीपी ट्रांस्पोर्टएसई जावा क्लास डाउनलोड / कॉपी किया है (कॉपी करने के बाद, कुछ कोड त्रुटियाँ हो सकती हैं, लेकिन वे सभी को जल्दी ठीक करने योग्य हैं) और मेरे पैकेज में जोड़े गए हैं:

https://github.com/mosabua/ksoap2-android/blob/master/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpTransportSE.java

मेरे कनेक्शन वर्ग से इस पंक्ति को हटा दिया गया:

import org.ksoap2.transport.HttpsTransportSE;

और इस कोड को मेरी नई HttpTransportSE.java फ़ाइल में प्रतिस्थापित किया गया:

if (debug) {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    byte[] buf = new byte[256];
                    while (true) {
                        int rd = is.read(buf, 0, 256);
                        if (rd == -1)
                            break;
                        bos.write(buf, 0, rd);
                    }
                    bos.flush();
                    buf = bos.toByteArray(); //Goes out of memory here
                    responseDump = new String(buf);
                    is.close();
                    is = new ByteArrayInputStream(buf);
    }

इसके साथ

if (debug) {
    FileOutputStream bos = new FileOutputStream(file);

            byte[] buf = new byte[256];

            while (true) {
                int rd = is.read(buf, 0, 256);
                if (rd == -1) {
                    break;
                }
                bos.write(buf, 0, rd);
            }
            bos.flush();
}

जहां "फाइल" एक नया फ़ाइल ऑब्जेक्ट है जैसे कि नया फ़ाइल ("/ sdcard /", "myfile.xml") उदाहरण के लिए


आपको इस समस्या को हल करने में मदद करने के लिए दो रणनीतियों:

  1. अपने SOAP XML स्ट्रीम को सीधे डिस्क पर सहेजें जैसे ही आप इसे डाउनलोड करते हैं इसे स्मृति में संग्रहीत न करें
  2. इसे SAX- शैली पार्सर का उपयोग करके पार्स करें, जहां आप स्मृति में पूरे DOM को लोड नहीं करते हैं, बल्कि विखंडों में इसे पार्स करते हैं।

XML के प्रकार के आधार पर आप संभाल रहे हैं, SAX पार्सर का उपयोग आमतौर पर कोड में कठिन है; आपको कई चीजों का ट्रैक रखना होगा, और आप अपने डीओएम ट्री के अनुभाग से "कूद" करने में सक्षम नहीं होंगे। लेकिन स्मृति खपत कम हो जाएगी।

ध्यान दें, हालांकि, कई "हाई-स्तरीय" नेटवर्क संचार लाइब्रेरी आमतौर पर स्मृति में संपूर्ण XML DOM को लोड करते हैं, जो यहां मामला हो सकता है संभवत: आपको एचटीटीपी कनेक्शन को स्वयं बनाना और प्रबंधित करना होगा, और उसके बाद परिणाम मैन्युअल रूप से पार्स करना होगा।







android-ksoap2