0

と を使用AsyncTaskgsonてフィードを解析していますが、すべて正常に動作しています。しかし、fragmentAPI 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を使用する2つのデバイスで常に強制終了しました。これは私の丸太猫です:

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)

これがどのように起こっているのか理解できません。他のフラグメントでもほぼ同じ型コードを使用しましたが、うまく機能しました。これを含む 2 つのフラグメントだけがこの問題に遭遇します。

4

2 に答える 2

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);
        }
    }
}
于 2013-08-18T20:15:25.077 に答える
1

JSON の読み取りとデータの処理の両方をバックグラウンド スレッドで実行する必要があります ( doInBackground)。ストリームをインスタンス化しても、ストリーム全体がメモリに読み込まれず、ストリームから読み取られた read メソッドが呼び出されるため、UI スレッドでネットワーク アクティビティが実行されますが、これは > API レベル 11 では無効です。

于 2013-08-18T20:15:46.643 に答える