I'm using the gson reader to read through an array of json objects, get the values that I want out of them and create smaller objects.
Everything works fine for most json files that I have tested, but there is one that gives me the following logcat error:
03-06 13:13:35.859: E/AndroidRuntime(3025): FATAL EXCEPTION: AsyncTask #2
03-06 13:13:35.859: E/AndroidRuntime(3025): java.lang.RuntimeException: An error occured while executing doInBackground()
03-06 13:13:35.859: E/AndroidRuntime(3025): at android.os.AsyncTask$3.done(AsyncTask.java:299)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
03-06 13:13:35.859: E/AndroidRuntime(3025): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.lang.Thread.run(Thread.java:856)
03-06 13:13:35.859: E/AndroidRuntime(3025): Caused by: java.lang.OutOfMemoryError
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:124)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.lang.StringBuilder.append(StringBuilder.java:271)
03-06 13:13:35.859: E/AndroidRuntime(3025): at com.google.gson.stream.JsonReader.nextQuotedValue(JsonReader.java:988)
03-06 13:13:35.859: E/AndroidRuntime(3025): at com.google.gson.stream.JsonReader.nextString(JsonReader.java:811)
03-06 13:13:35.859: E/AndroidRuntime(3025): at example.myapp.LoadFileFragment.getTwo(LoadFileFragment.java:676)
03-06 13:13:35.859: E/AndroidRuntime(3025): at example.myapp.LoadFileFragment.getInfo(LoadFileFragment.java:618)
03-06 13:13:35.859: E/AndroidRuntime(3025): at example.myapp.LoadFileFragment.access$1(LoadFileFragment.java:525)
03-06 13:13:35.859: E/AndroidRuntime(3025): at example.myapp.LoadFileFragment$DownloadTask.doInBackground(LoadFileFragment.java:184)
03-06 13:13:35.859: E/AndroidRuntime(3025): at example.myapp.LoadFileFragment$DownloadTask.doInBackground(LoadFileFragment.java:1)
03-06 13:13:35.859: E/AndroidRuntime(3025): at android.os.AsyncTask$2.call(AsyncTask.java:287)
03-06 13:13:35.859: E/AndroidRuntime(3025): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
03-06 13:13:35.859: E/AndroidRuntime(3025): ... 5 more
Here is the method that is failing, which basically checks to see if one key within a nested object has a value, gets the string if it does, checks to see if another key within the same object has a value and if it does adds them together before returning.
private String getTwo(JsonReader reader, String n1, String n2) throws IOException{
String str="";
String str1="";
String str2="";
reader.beginObject();
while (reader.hasNext()) {
str="";
String nm = reader.nextName();
if(nm.equals(n1)&& reader.peek() != JsonToken.NULL){
str1=reader.nextString();
}
else if(nm.equals(n2)&& reader.peek() != JsonToken.NULL){
str2=" "+reader.nextString();
}
else {
reader.skipValue();
}
}
str=str1+str2;
return str;
}
The logic is sound - it works on thousands of other objects I have tested. I get this error every time when it comes to one particular object that has a string that is about 1300 chars long - is that the problem? And if so, is there some way of doing a length check beforehand and maybe splitting the string up? Or is there some better way to be doing this? I tried using StringBuilder, but got the same error on the same object.
One very strange thing is that I only get the error on my tablet (running ICS) - on my phone (running gingerbread) it works fine
UPDATE
So, this is the least memory-consumptive way I can think of doing this:
StringBuilder strb=new StringBuilder();
private String getTwo(JsonReader reader, String n1, String n2) throws IOException{
strb.setLength(0);
strb.append("");
reader.beginObject();
while (reader.hasNext()) {
String nm = reader.nextName();
if(nm.equals(n1)&& reader.peek() != JsonToken.NULL){
strb.append(reader.nextString());
}
else if(nm.equals(n2)&& reader.peek() != JsonToken.NULL){
strb.append(reader.nextString());
}
else {
reader.skipValue();
}
}
return strb.toString();
}
but it still crashes in exactly the same spot... It can't be the length of the string (1300 characters is relatively nothing as far as I can tell), but I did notice that the string in question has various html tags in it. Other, shorter strings with html tags don't seems to pose a problem, so it seems to be a combination of length and tags. This unresolved post seems to be dealing with a very similar issue... Any thoughts?