簡體   English   中英

BufferedReader.readLine()會阻塞一段時間

[英]BufferedReader.readLine() blocks for a while

我正在嘗試獲取http響應的字符串(只是一個JSON對象),有時這段代碼等待無限時間

line = reader.readLine()

可能是這種行為的原因是Internet連接不良(我使用3G調制解調器),但是我需要一個穩定的解決方案來避免這種無限鎖定。 可以采取什么措施避免這種情況?

HttpResponse response = httpClient.execute(httpPost);

InputStream content = null;
JSONObject json_obj;
if (response.getStatusLine().getStatusCode() == 200) {
    HttpEntity entity = response.getEntity();

    try {
        content = entity.getContent();

        BufferedReader reader = new BufferedReader(new InputStreamReader(content, "UTF-8"), 256);
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
    } catch (Exception e) {}
}

您可以指定讀取超時:

HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);

應該將讀取超時設置為30秒。 可能還需要指定連接超時:

client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);
readLine()

否則任何網絡/ IO都應在后台線程中完成,以防止主線程被鎖定。

如果您在Android 4.0+上測試代碼,您還將看到主線程不再允許聯網,並且將引發異常。

看一下AsyncTask ,它是在后台線程上運行此類任務的一種簡單而輕松的方法。

避免“無限”鎖定的一個好的解決方案是在一個單獨的線程中進行此http調用,並使用Handler通知主線程該信息已加載並可以按需要使用它。

這也是我自己也使用SaxParser的示例:

public void SearchFromSuperClass(String text)
{   
    mHandler = new Handler();
    Thread t = new Thread(){
        public void run() {
            try {
              String strurl="URLTOPATH";
              URL url = new  URL(strurl);
              SAXParserFactory factory = SAXParserFactory.newInstance();

              SAXParser parser = factory.newSAXParser();
              FundsHandlerRanking handler = new FundsHandlerRanking();
              parser.parse(url.openConnection().getInputStream(), handler);
              search_response = handler.getrankings();


              mHandler.post(mUpdateResults);
            } catch (Exception e) {
                search_response = null;
                mHandler.post(mUpdateResults);

            }

        }
    };

    t.start();
}
final Runnable mUpdateResults = new Runnable() {
    public void run() {
        updateResultsInUi();
    }
};

private void updateResultsInUi() {

    try
    {
        if(search_response != null)
        {
            lview.setAdapter(new SearchRankingAdapter(mycontext, search_response, false));
        }
        Pdialog.dismiss();
    }
    catch (Exception e) {
        lview.setAdapter(null);
        if (Pdialog.isShowing())
        {
            Pdialog.dismiss();
        }
    }
}

使用mHandler.post(...),可以將調用放入要發送到主UI線程的隊列中,在那里,您可以毫無問題地修改UI對象(不能在Main線程之外修改UI對象)。

希望這可以幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM