我正在使用AsyncTask
和gson
来解析Feed,一切正常。但在一个fragment
中,我在API 11上面的设备上被迫关闭我的应用程序。在API 11以下的设备中可以正常使用。这是我的代码:
public class LatestSubmissions extends SherlockListFragment {
SharedPreferences prefs;
LatestSubmissionsAdapter adapter = null;
ArrayList<HashMap<String, String>> submissions = new ArrayList<HashMap<String, String>>();
private GetSubmissionsListTask submissionTask = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ConnectionDetector cd = new ConnectionDetector(getSherlockActivity());
if (cd.isConnectingToInternet()) {
prefs = getSherlockActivity().getSharedPreferences(
CommonUtils.PREFERENCE_NAME, 0);
submissionTask = new GetSubmissionsListTask();
submissionTask.execute(CommonUtils.USER_SUBMISSION_URL
+ prefs.getString(CommonUtils.KEY_USER_ID, "339") + "/10");
} else {
MainActivity.networkAvailabilityNotice(getSherlockActivity());
}
return super.onCreateView(inflater, container, savedInstanceState);
}
protected class GetSubmissionsListTask extends
AsyncTask<String, Void, InputStreamReader> {
@Override
protected InputStreamReader doInBackground(String... params) {
return new JSONDownloader().getJSONStringFromUrl(params[0]);
}
@Override
protected void onPostExecute(InputStreamReader isr) {
if (isr != null) {
MainActivity activity = (MainActivity) getSherlockActivity();
JsonReader reader = new JsonReader(isr);
try {
reader.beginObject();
reader.nextName(); // name
reader.skipValue();
reader.nextName(); // uname
reader.skipValue();
String subs = reader.nextName(); // subs
if (subs.equals(CommonUtils.KEY_SUBMISSION)) {
reader.beginArray();
while (reader.hasNext()) {
HashMap<String, String> map = new HashMap<String, String>();
reader.beginArray();
reader.skipValue(); // submission id
String txt = "Latest problem";
Problems obj = MainActivity.problems.get(reader
.nextInt());
if (obj != null) {
txt = obj.getProblemsInfo();
}
map.put(CommonUtils.KEY_PROBLEM_ID, txt);
Verdict verdict = activity.verdicts.get(reader
.nextString()); // verdict id
map.put(CommonUtils.KEY_VERDICT_COLOR,
verdict.verdictColorHex);
map.put(CommonUtils.KEY_VERDICT_ID, verdict.name);
Double execTime = reader.nextDouble() / 1000; // execution
// time
map.put(CommonUtils.KEY_RUNTIME,
execTime.toString() + "s");
reader.skipValue(); // submission time
map.put(CommonUtils.KEY_LANGUAGE_ID,
activity.languageCode.get(reader
.nextString())); // lanugage
// id
map.put(CommonUtils.KEY_SUBMISSION_RANK,
reader.nextString()); // rank
submissions.add(map);
reader.endArray();
}
reader.endArray();
}
reader.endObject();
reader.close();
} catch (IOException e) {
if (CommonUtils.isDebuggable) {
Log.e("GSON Parser",
"Error parsing data " + e.toString());
}
}
Collections.reverse(submissions);
adapter = new LatestSubmissionsAdapter(getSherlockActivity(),
submissions);
setListAdapter(adapter);
}
}
}
@Override
public void onStop() {
super.onStop();
if (submissionTask != null
&& submissionTask.getStatus() != AsyncTask.Status.FINISHED) {
submissionTask.cancel(true);
}
}
}
我已经在几个具有不同API级别的设备和模拟器中进行了测试,并且它总是在我的两个带有ICS和Jellybean的设备中被迫关闭。 这是我的日志猫:
08-19 01:57:16.961: E/AndroidRuntime(710): FATAL EXCEPTION: main
08-19 01:57:16.961: E/AndroidRuntime(710): android.os.NetworkOnMainThreadException
08-19 01:57:16.961: E/AndroidRuntime(710): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
08-19 01:57:16.961: E/AndroidRuntime(710): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:163)
08-19 01:57:16.961: E/AndroidRuntime(710): at libcore.io.IoBridge.recvfrom(IoBridge.java:503)
08-19 01:57:16.961: E/AndroidRuntime(710): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
08-19 01:57:16.961: E/AndroidRuntime(710): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
08-19 01:57:16.961: E/AndroidRuntime(710): at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
08-19 01:57:16.961: E/AndroidRuntime(710): at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
08-19 01:57:16.961: E/AndroidRuntime(710): at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:134)
08-19 01:57:16.961: E/AndroidRuntime(710): at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:174)
08-19 01:57:16.961: E/AndroidRuntime(710): at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:159)
08-19 01:57:16.961: E/AndroidRuntime(710): at java.io.InputStreamReader.read(InputStreamReader.java:244)
08-19 01:57:16.961: E/AndroidRuntime(710): at com.google.gson.stream.JsonReader.fillBuffer(JsonReader.java:1263)
08-19 01:57:16.961: E/AndroidRuntime(710): at com.google.gson.stream.JsonReader.nextQuotedValue(JsonReader.java:1005)
08-19 01:57:16.961: E/AndroidRuntime(710): at com.google.gson.stream.JsonReader.nextString(JsonReader.java:811)
08-19 01:57:16.961: E/AndroidRuntime(710): at me.kaidul.uhunt.RankList$GetRankListTask.onPostExecute(RankList.java:85)
08-19 01:57:16.961: E/AndroidRuntime(710): at me.kaidul.uhunt.RankList$GetRankListTask.onPostExecute(RankList.java:1)
08-19 01:57:16.961: E/AndroidRuntime(710): at android.os.AsyncTask.finish(AsyncTask.java:602)
08-19 01:57:16.961: E/AndroidRuntime(710): at android.os.AsyncTask.access$600(AsyncTask.java:156)
08-19 01:57:16.961: E/AndroidRuntime(710): at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
08-19 01:57:16.961: E/AndroidRuntime(710): at android.os.Handler.dispatchMessage(Handler.java:99)
08-19 01:57:16.961: E/AndroidRuntime(710): at android.os.Looper.loop(Looper.java:137)
08-19 01:57:16.961: E/AndroidRuntime(710): at android.app.ActivityThread.main(ActivityThread.java:4424)
08-19 01:57:16.961: E/AndroidRuntime(710): at java.lang.reflect.Method.invokeNative(Native Method)
08-19 01:57:16.961: E/AndroidRuntime(710): at java.lang.reflect.Method.invoke(Method.java:511)
08-19 01:57:16.961: E/AndroidRuntime(710): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-19 01:57:16.961: E/AndroidRuntime(710): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-19 01:57:16.961: E/AndroidRuntime(710): at dalvik.system.NativeStart.main(Native Method)
我无法弄清楚这是怎么回事。我在其他片段中使用了几乎相同的类型代码并且运行良好。只有两个片段包含这个问题。
答案 0 :(得分:4)
您需要在doInBackground
中完整读取输入流。您现在正在做的就是在doInBackground
中打开连接并获取结果的阅读器。但是,您正试图在onPostExecute
中实际读取网络中正在主线程上执行的数据。
protected class GetSubmissionsListTask extends
AsyncTask<String, Void, ArrayList<HashMap<String, String>>> {
@Override
protected ArrayList<HashMap<String, String>> doInBackground(String... params) {
InputStreamReader isr = new JSONDownloader().getJSONStringFromUrl(params[0]);
ArrayList<HashMap<String, String>> result = null;
if (isr != null) {
result = new ArrayList<HashMap<String, String>>();
MainActivity activity = (MainActivity) getSherlockActivity();
JsonReader reader = new JsonReader(isr);
try {
reader.beginObject();
reader.nextName(); // name
reader.skipValue();
reader.nextName(); // uname
reader.skipValue();
String subs = reader.nextName(); // subs
if (subs.equals(CommonUtils.KEY_SUBMISSION)) {
reader.beginArray();
while (reader.hasNext()) {
HashMap<String, String> map = new HashMap<String, String>();
reader.beginArray();
reader.skipValue(); // submission id
String txt = "Latest problem";
Problems obj = MainActivity.problems.get(reader
.nextInt());
if (obj != null) {
txt = obj.getProblemsInfo();
}
map.put(CommonUtils.KEY_PROBLEM_ID, txt);
Verdict verdict = activity.verdicts.get(reader
.nextString()); // verdict id
map.put(CommonUtils.KEY_VERDICT_COLOR,
verdict.verdictColorHex);
map.put(CommonUtils.KEY_VERDICT_ID, verdict.name);
Double execTime = reader.nextDouble() / 1000; // execution
// time
map.put(CommonUtils.KEY_RUNTIME,
execTime.toString() + "s");
reader.skipValue(); // submission time
map.put(CommonUtils.KEY_LANGUAGE_ID,
activity.languageCode.get(reader
.nextString())); // lanugage
// id
map.put(CommonUtils.KEY_SUBMISSION_RANK,
reader.nextString()); // rank
result.add(map);
reader.endArray();
}
reader.endArray();
}
reader.endObject();
} catch (IOException e) {
if (CommonUtils.isDebuggable) {
Log.e("GSON Parser",
"Error parsing data " + e.toString());
}
result = null;
} finally {
reader.close(); // always need to close, even after an exception
}
}
if (result != null) Collections.reverse(result);
return result;
}
@Override
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
if (result != null) {
submissions = result; // do you still need this?
adapter = new LatestSubmissionsAdapter(getSherlockActivity(),
result);
setListAdapter(adapter);
}
}
}
答案 1 :(得分:1)
您应该在后台线程(doInBackground
)中同时执行JSON读取和数据处理。实例化流不会将整个流读入存储器,调用从流读取的读取方法,从而在UI线程上执行网络活动,这在&gt;上是非法的。 API级别11。