2011-02-09 15 views
10

Tôi có một ứng dụng mà tôi cần tải xuống một lượng lớn dữ liệu qua cuộc gọi SOAP tới dịch vụ web vào ứng dụng khi nó được chạy lần đầu tiên. Câu trả lời sau đó được gửi đến một hàm chuyển đổi XML và lưu trữ dữ liệu trong một tệp tin db.Phản hồi SOAP rất lớn - Lỗi Android hết bộ nhớ

Dữ liệu có kích thước lớn hơn 16MB và tôi có một java.lang.OutOfMemoryError mỗi lần.

Sửa đổi dịch vụ web để cung cấp lượng dữ liệu nhỏ hơn không phải là một tùy chọn.

Có cách nào để có thể tải xuống dữ liệu lớn không? Một cái gì đó giống như một InputStream có lẽ?

Đây là mã của tôi

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); 

} 

bất cứ ai có thể đề xuất những gì nên được thực hiện trong trường hợp này?

Trân trọng cảm ơn Mukul

+0

tôi nghĩ rằng vtd-xml chắc chắn có thể giúp giảm mức sử dụng bộ nhớ. –

+0

@ vtd-xml-author - nó cũng hoạt động cho android? –

Trả lời

5

Hai chiến lược để giúp bạn giải quyết vấn đề này:

  1. Lưu dòng XML SOAP của bạn trực tiếp vào đĩa khi bạn tải nó. Không lưu trữ nó trong bộ nhớ.
  2. Phân tích cú pháp bằng cách sử dụng trình phân tích cú pháp theo kiểu SAX, nơi bạn không tải toàn bộ DOM trong bộ nhớ, mà là phân tích cú pháp theo khối.

Tùy thuộc vào loại XML bạn đang xử lý, việc sử dụng trình phân tích SAX thường khó hơn trong mã; bạn sẽ phải tự theo dõi nhiều thứ và bạn sẽ không thể "nhảy" từ phần này sang phần khác của cây DOM. Nhưng mức tiêu thụ bộ nhớ sẽ thấp hơn. Tuy nhiên, hãy lưu ý rằng nhiều thư viện liên lạc mạng "cấp cao" thường tải toàn bộ DOM XML trong bộ nhớ, đây có thể là trường hợp ở đây. Có thể bạn sẽ phải tự tạo và quản lý kết nối HTTP và sau đó phân tích cú pháp kết quả theo cách thủ công.

+1

Xin chào Adrian, Cảm ơn bạn đã trả lời, tôi đã thử điều này và nó hoạt động tốt, trong trường hợp này, tệp XML chính nó có kích thước khoảng 8 MB. Vui lòng xem câu trả lời của tôi bên dưới, tôi cũng đã dán mã để làm điều đó, để tham khảo trong tương lai –

6

Chỉ cần một bản cập nhật, tôi phát hiện ra rằng "gọi là" phương pháp trong AndroidHttpTransport đã chạy ra khỏi bộ nhớ tại dòng này -

  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); 

cuộc gọi đến toByteArray mất rất nhiều của bộ nhớ, vì vậy để khắc phục điều này, thay vì chuyển đổi phản hồi thành mảng byte, tôi bây giờ trực tiếp ghi nó vào một tệp XML, và điều này được lưu tại một vị trí mà tôi chọn. Tại đây -

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(); 
} 

Thiết bị không còn hết bộ nhớ và tôi có phương thức phân tích cú pháp tùy chỉnh lấy XML này và ghi nó vào DB.

+3

Bạn đã sử dụng nó như thế nào với 'SoapObject' trong' SoapSerializationEnvelope'? Bạn có thể hiển thị toàn bộ ví dụ của mình bằng cách gọi dịch vụ web bằng ksoap2 và ghi kết quả vào tệp thay vì tuần tự hóa chúng thành 'SoapObject' không? –

+0

Tôi cũng cần ví dụ của bạn. Xin vui lòng gửi nó – kinghomer

+0

Cảm ơn Mukul cho câu trả lời của bạn.Tuy nhiên, nó không rõ ràng như thế nào bạn đã nhận được response.Can u xin vui lòng cung cấp toàn bộ phương pháp của bạn nhận được phản ứng và lưu nó vào một tập tin.What về việc gọi các webservice makeCall (phong bì, methodName, soapAction) ;? – joy

1

Đã sửa lỗi!

tôi tải/sao chép HttpTransportSE lớp java từ đây (sau khi sao chép, một số lỗi mã có thể xảy ra, nhưng tất cả chúng đều nhanh chóng fixable) và thêm vào gói của tôi:

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

ra khỏi lớp kết nối của tôi hàng này :

import org.ksoap2.transport.HttpsTransportSE; 

và thay thế mã này trong HttpTransportSE mới của tôi.file 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); 
    } 

với điều này

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(); 
} 

nơi "tập tin" là một đối tượng tập tin đơn giản như tập tin mới ("/ sdcard /", "myFile.xml") ví dụ

+1

Tôi đã thực hiện điều này trong ksoap2-android 3.0.0-RC.5-SNAPSHOT. Bạn có thể thử nếu nó hoạt động cho bạn? –

+0

Ok tôi sẽ thử và đăng kết quả càng sớm càng tốt – kinghomer

+0

@kinghomer Tôi đã sử dụng cùng một mã và sau đó không bao giờ có ngoại lệ OutOfMemory nhưng bây giờ tôi nhận được org.xmlpull.v1.XmlPullParserException: loại không mong muốn (vị trí: END_DOCUMENT null @ 1: 1 trong [email protected]) Trợ giúp của bạn sẽ giống như kim cương đối với tôi .. – Araju