2

HTTP リクエストで奇妙な動作が発生しています。この呼び出しが戻ってくることはないと言っているユーザーが何人かいます (非同期呼び出しであることを示すスピナーが消えることはありません)。以前にこれが発生するのを見たことがありますが、Charles Proxy を経由するエミュレーターが原因であると考えました。私はまだ実際の電話でそれを見たことがありません。

何が原因なのかわからないので、ここに投稿します。Jackson を使用して結果を値オブジェクトに逆シリアル化する呼び出しは次のとおりです。エミュレーターのフリーズが見られた 2 つのスポットは、httpclient.execute(httpGet); です。getObjectMapper().readValue(jp, SyncVO.class);.

デバッグ中に、問題のあるステートメントをステップ オーバーすると、デバッガーがステップ実行の制御を取り戻すことができませんでした。その間、リクエストが送信され、Charles を介してサーバーから戻ってくるのがわかります。アプリが応答を取得していないようで、ただそこに座っているだけです.

というわけで、これがコードです。助けてくれてありがとう!

public SyncVO sync(String userId, long lastUpdate, boolean includeFetch) throws IOException {
    SyncVO result = null;

    String url = BASE_URL + "users/" + userId + "/sync" + "?" + "fetch=" + includeFetch;

    if (lastUpdate > 0) {
        url += "&updatedSince=" + lastUpdate;
    }

    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpGet httpGet = new HttpGet(url);

    httpGet.setHeader("Accept", "application/json");
    httpGet.setHeader("Accept-Encoding", "gzip");
    httpGet.setHeader(AUTHORIZATION, BEARER + " " + mOAuthToken);
    httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, USER_AGENT_STRING);
    httpclient.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);

    HttpResponse response = httpclient.execute(httpGet);

    if (isUnauthorized(response)) {
        APPLICATION.needReauthentication();
        return null;
    }

    if (response != null) {
        InputStream stream = response.getEntity().getContent();
        Header contentEncoding = response.getFirstHeader("Content-Encoding");
        if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
            stream = new GZIPInputStream(stream);
        }

        InputStreamReader inReader = new InputStreamReader(stream, "UTF-8");
        JsonParser jp = mJsonFactory.createJsonParser(inReader);
        result = getObjectMapper().readValue(jp, SyncVO.class);
    }   

    return result;
}

private ObjectMapper getObjectMapper() {
    return (new ObjectMapper()
        .configure(Feature.AUTO_DETECT_FIELDS, true)
        .configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true));
}
4

4 に答える 4

1

接続タイムアウトとソケット読み取りを確実に使用し、サーバーからの最悪の事態に備える必要があります。ネットワーク操作が100%予測可能になることは決してなく、クライアントが実行できることはあまりないので、最適にコーディングするようにしてください。

httpParameters = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 5000);
HttpConnectionParams.setSoTimeout(httpParameters, 10000);

asyncTask.cancel(true);を使用してタスクをキャンセルすることもできます。

于 2012-04-17T22:21:01.170 に答える
1

その理由は、あなたがstream開いたままにしているからです。このように、responseは宙ぶらりんのままです。これは、グローバル変数httpClientも不安定なままであり、クライアントを再利用するときに新しいエンティティを取得できないことを意味します。

close()ストリームを終了した後に呼び出す必要があります。

stream.close();
于 2014-04-28T15:14:35.643 に答える
-1

ネットワーク呼び出しには時間がかかり、UI スレッドがブロックされます。ジャクソンの逆シリアル化コードと同じです。このようなものは別のスレッドに置く必要があります。これを行う簡単な方法については、AsyncTaskを参照してください。

于 2012-04-17T22:01:57.640 に答える