2016-01-26 23 views
10

Realizzo un'app per Android che esegue un servizio Web ASP.NET. Webservice invia un oggetto JSON e l'app analizza l'oggetto e lo visualizza sullo schermo. In un caso, l'oggetto JSON è troppo grande e viene visualizzato l'errore Transazione raccoglitore non riuscito. La mia soluzione è quella di ottenere quell'oggetto JSON e incorporarlo nel codice dell'app, in modo che non abbia bisogno di ottenere quell'oggetto JSON dal server. Puoi dire altre cose che posso fare per questo problema? Oppure puoi dirmi come ottenere quell'oggetto JSON da Webservice? Grazie.Come gestire un oggetto JSON di grandi dimensioni su Android

+1

Potrebbe fornire come 'grande' è? come sopra xxx Mb? Scarica l'intero JSON e l'analisi può essere sia costosa. – sakiM

+0

Perché lo stai recuperando da un server e perché lo stai salvando come json se è statico e può essere spedito nell'app? – rds

+0

Questo problema non è dovuto al file json, c'è qualcos'altro da vedere. È necessario allegare output logcat se si desidera una soluzione. – chandil03

risposta

8

Invio dei dati di grandi dimensioni dal server al cellulare. JSON è leggero. Se si desidera passare i dati in modo più efficiente, passarli in pagine. Se si desidera utilizzare il protocollo più leggero di JSON, implementare il protocollo google di seguito che è molto utile, che supporta le principali lingue. Di seguito sono riportati i dati di serie più piccoli. Protocollo di interscambio dati di Google.

1.Google Protocol

2.Flat Buffers

3.Nano-proto buffers

Spero che questo sarà utile voi.

4

Se i dati sono di grandi dimensioni, provare a salvarli nel database, quindi gestirli utilizzando SQLite. (ma non consigliato se dinamico)

Per analizzare l'oggetto json utilizzare gson o jackson. Ciò contribuirà a ridurre significativamente il consumo di memoria man mano che i dati di JSON vengono analizzati parzialmente. ottenere GSON, Jackson qui https://sites.google.com/site/gson/gson-user-guide http://jackson.codehaus.org/

un Jackson esempio http://www.mkyong.com/java/jackson-streaming-api-to-read-and-write-json/

+1

Consiglierei Jackson a GSON. Nei miei test, analizzando un oggetto JSON molto grande da un InputStream, il primo è circa il 25% più veloce e utilizza meno memoria. –

0

Si potrebbe integrare un JSON nel codice dell'app come lei ha suggerito, ma questo sarà un cattivo approccio se il JSON è dinamico. Quindi dovrai inviare un aggiornamento per la tua app ogni volta che cambia JSON.

Una soluzione migliore sarebbe quella di impaginare il JSON generato dal proprio WebService, ovvero suddividere il JSON in parti più piccole che è possibile recuperare sequenzialmente in chiamate API separate.

+0

Il problema è che non riesco a ottenere quel grosso JSON da Webservice, puoi dirmi come ottenerlo? Grazie. – jason

+0

L'uso dell'API di streaming delle librerie di GSON o di Jackson è una buona opzione, come suggerito in altre risposte su questo post. Ma dovresti farlo solo se non sei in grado di modificare l'output del tuo WebService. Sarebbe meglio suddividere per prima cosa l'output di WebService. Se non sei in grado di farlo, allora vai per lo streaming API. –

2

Prima cosa: se c'è un crash o un'eccezione nel codice, probabilmente vorrai postarlo. "Eccezione Binder fallito" è un po 'troppo vago per capire cosa stai facendo.

Se davvero si vuole spedire il vostro app Android con JSON embeddd al suo interno (per evitare di dover prendere da un server, prendere in considerazione l'archiviazione come una risorsa e accedervi utilizzando AssetManager. Che, fondamentalmente, rilascia il file con il JSON in la cartella delle risorse dell'app e leggerle con AssetManager.

Se si desidera scaricarlo dal server e agire su di esso, considerare l'utilizzo delle API di streaming per scaricare e analizzare il JSON. Il JSONObject di Android non lo fa e insiste per avere l'intera stringa JSON in memoria prima di poter essere analizzata

Se si desidera eseguire lo streaming direttamente da un download di URL in un parser di streaming (ad esempio s GSON), prova qualcosa seguendo queste linee. In primo luogo ottenere un InputStream dall'URL si sta cercando di recuperare:

URL u = new URL(url); 
    URLConnection conn = u.openConnection(); 
    InputStream is = new BufferedInputStream(conn.getInputStream()); 

Poi feed che InputStream direttamente sul tuo parser streaming. Questo dovrebbe evitare che la necessità di tirare l'intera risposta in memoria prima analisi, ma avrete ancora bisogno di memoria sufficiente per contenere tutti gli oggetti che il parser crea:

GsonBuilder gb = new GsonBuilder(); // configure this as necessary 
    Gson gson = gb.create(); 
    final Result response = gson.fromJson(
     new InputStreamReader(is, Charset.forName("UTF-8")), 
     Result.class 
    ); 

"Risultato" qui è una classe che conterrà i dati dalla risposta JSON. Dovrai assicurarti che tutti i mapping funzionino per i tuoi dati, quindi leggi su GSON e fai tutto il possibile per il tuo caso.

È anche possibile utilizzare GSON per analizzare i dati JSON se lo si memorizza in una risorsa. Basta passarlo all'inputstream dei dati dell'asset e funziona allo stesso modo.

0

Preferibilmente cercare di rompere l'oggetto JSON per piccoli oggetti e ottenere da webService,

o ottenere dati in parti e se u cant farlo

Devi usare un parser JSON in streaming. Per Android u possibile utilizzare questi 2:

  1. GSON

  2. Jackson

GSON Streaming è spiegato in: https://sites.google.com/site/gson/streaming

Personalmente, come GSON.

0

La seguente classe ApiUrlClass.java ha tutti i metodi necessari. Si prega di leggere i commenti della classe che ho scritto. Questo ti aiuterà a fare quello che ti serve. Questo utilizza anche trasparente.

import android.graphics.Bitmap; 
import android.net.Uri; 
import android.os.Build; 
import android.util.Log; 
import org.apache.http.entity.mime.HttpMultipartMode; 
import org.apache.http.entity.mime.content.ByteArrayBody; 
import org.apache.http.entity.mime.content.ContentBody; 
import org.apache.http.entity.mime.content.StringBody; 
import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.ByteArrayOutputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.net.HttpURLConnection; 
import java.net.SocketTimeoutException; 
import java.net.URL; 
import java.net.UnknownHostException; 

import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLPeerUnverifiedException; 

/* 
Usage of the class 

Create all the necessary API Call methods you need. 
And either use a Thread or AsyncTask to call the following. 

    JSONObject response = ApiUrlCalls.login("username", "passowrd"); 

After the response is obtained, check for status code like 

    if(response.getInt("status_code") == 200){ 
     //TODO: code something 
    } else { 
     //TODO: code something 
    } 
*/ 

public class ApiUrlCalls { 

    private String HOST = "https://domain/path/"; //This will be concated with the function needed. Ref:1 

    /* 
     Now utilizing the method is so simple. Lets consider a login function, which sends username and password. 
     See below for example. 
    */ 

    public static JSONObject login(String username, String password){ 

     String functionCall = "login"; 
     Uri.Builder builder = new Uri.Builder() 
       .appendQueryParameter("username", username) 
       .appendQueryParameter("password", password); 

     /* 
      The return calls the apiPost method for processing. 
      Make sure this should't happen in the UI thread, orelse, NetworkOnMainThread exception will be thrown. 
     */ 
     return apiPost(builder, functionCall); 

    } 

    /* 
     This method is the one which performs POST operation. If you need GET, just change it 
     in like Connection.setRequestMethod("GET") 
    */ 
    private static JSONObject apiPost(Uri.Builder builder, String function){ 
     try { 
      int TIMEOUT = 15000; 
      JSONObject jsonObject = new JSONObject(); 
      try { 
       URL url = null; 
       String response = ""; 

       /* 
        Ref:1 
        As mentioned, here below, in case the function is "login", 
        url looks like https://domain/path/login 

        This is generally a rewrited form by .htaccess in server. 
        If you need knowledge on RESTful API in PHP, refer 
        http://stackoverflow.com/questions/34997738/creating-restful-api-what-kind-of-headers-should-be-put-out-before-the-response/35000332#35000332 

        I have answered how to create a RESTful API. It matches the above URL format, it also includes the .htaccess 
       */ 

       url = new URL(HOST + function); 

       HttpsURLConnection conn = null; 
       conn = (HttpsURLConnection) url.openConnection(); 
       assert conn != null; 
       conn.setReadTimeout(TIMEOUT); 
       conn.setConnectTimeout(TIMEOUT); 
       conn.setRequestMethod("POST"); 
       conn.setDoInput(true); 
       conn.setDoOutput(true); 

       String query = builder.build().getEncodedQuery(); 

       OutputStream os = conn.getOutputStream(); 
       BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); 
       writer.write(query); 
       writer.flush(); 
       writer.close(); 
       os.close(); 
       conn.connect(); 


       int responseCode = conn.getResponseCode(); 
       String responseMessage = conn.getResponseMessage(); 
       jsonObject.put("status_code", responseCode); 
       jsonObject.put("status_message", responseMessage); 

       /*The if condition below will check if status code is greater than 400 and sets error status 
       even before trying to read content, because HttpUrlConnection classes will throw exceptions 
       for status codes 4xx and 5xx. You cannot read content for status codes 4xx and 5xx in HttpUrlConnection 
       classes. 
       */ 

       if (jsonObject.getInt("status_code") >= 400) { 
        jsonObject.put("status", "Error"); 
        jsonObject.put("msg", "Something is not good. Try again later."); 
        return jsonObject; 
       } 

       String line; 
       BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); 

       while ((line = br.readLine()) != null) { 
        response += line; 
       } 
       //Log.d("RESP", response); 

       /* 
        After the actual payload is read as a string, it is time to change it into JSON. 
        Simply when it starts with "[" it should be a JSON array and when it starts with "{" 
        it is a JSONObject. That is what hapenning below. 
       */ 
       if(response.startsWith("[")) { 
        jsonObject.put("content", new JSONArray(response)); 
       } 
       if(response.startsWith("{")){ 
        jsonObject.put("content", new JSONObject(response)); 
       } 


      } catch(UnknownHostException e) { 
      //No explanation needed :) 
       jsonObject.put("status", "UnknownHostException"); 
       jsonObject.put("msg", "Check your internet connection"); 
      } catch (SocketTimeoutException){ 
      //This is when the connection timeouts. Timeouts can be modified by TIMEOUT variable above. 
       jsonObject.put("status", "Timeout"); 
       jsonObject.put("msg", "Check your internet connection"); 
      } catch (SSLPeerUnverifiedException se) { 
      //When an untrusted SSL Certificate is received, this happens. (Only for https.) 
       jsonObject.put("status", "SSLException"); 
       jsonObject.put("msg", "Unable to establish secure connection."); 
       se.printStackTrace(); 
      } catch (IOException e) { 
      //This generally happens when there is a trouble in connection 
       jsonObject.put("status", "IOException"); 
       jsonObject.put("msg", "Check your internet connection"); 
       e.printStackTrace(); 
      } catch(FileNotFoundException e){ 
      //There is no chance that this catch block will execute as we already checked for 4xx errors 
       jsonObject.put("status", "FileNotFoundException"); 
       jsonObject.put("msg", "Some 4xx Error"); 
       e.printStackTrace(); 
      } catch (JSONException e){ 
      //This happens when there is a troble reading the content, or some notice or warnings in content, 
      //which generally happens while we modify the server side files. Read the "msg", and it is clear now :) 
       jsonObject.put("status", "JSONException"); 
       jsonObject.put("msg", "We are experiencing a glitch, try back in sometime."); 
       e.printStackTrace(); 
      } return jsonObject; 

     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

} 
1

Stai passando dati tra le attività? Voglio dire stai cercando di passare l'oggetto big data (ricevuto dal WS) a un'altra attività usando intent.putExtra()?

+0

Sì, lo sto facendo. In realtà l'app si sta bloccando esattamente in quel punto. – jason

+1

Quindi molto probabilmente perché c'è un limite tra la dimensione dei dati che è possibile passare tramite un intento. Prova a salvare i dati in un file e poi passa il percorso file tramite l'intento. Nell'attività successiva, utilizzare il percorso file ricevuto per ottenere un riferimento al file salvato. –

Problemi correlati