【问题标题】:Do POST request with Android DefaultHTTPClient cause freeze on execute()使用 Android DefaultHTTPClient 执行 POST 请求会导致 execute() 冻结
【发布时间】:2016-04-02 05:57:51
【问题描述】:

我需要将数据发布到服务器。 我使用此代码:

HttpClient client = new DefaultHttpClient();
try {

    HttpPost httppost = new HttpPost(serverUrl);

    StringEntity se = new StringEntity(data);
    httppost.setEntity(se);
    httppost.setHeader("Accept", "application/json");
    httppost.setHeader("Content-type", "application/json");

    // Execute HTTP Post Request
    HttpResponse response = client.execute(httppost);
    int statusCode = response.getStatusLine().getStatusCode();
    Log.i(TVProgram.TAG, "ErrorHandler post status code: " + statusCode);

} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (client != null) {
        client.getConnectionManager().shutdown();
    }
}

但问题是 Android 在 execute() 方法上冻结,应用程序被阻止,一段时间后 Android 告诉我应用程序没有响应。

我尝试调试 SDK 类,但它冻结在第 103 行的 AbstractSessionInputBuffer 类中

l = this.instream.read(this.buffer, off, len);

我也试过在单独的线程中运行请求,但同样的问题。

我在 Android 2.1(模拟器)和 Android 2.2 真实移动设备上对其进行了测试。
我还尝试设置 HTTP 代理并使用 Fiddler 来检查服务器接收到的 HTTP 通信数据,服务器也发送正确的答案和 HTTP 代码 200。一切似乎都很好。

请问有什么问题吗?

更新:当我使用作为 Android 2.2 SDK 一部分的 AndroidHttpClient 时,它运行良好。但它不在早期版本的 Android 中。所以我现在将它的源代码包含在我的应用程序中。但是AndroidHttpClient内部使用的是DefaultHTTPClient,所以问题出在DefaultHttpClient的配置上。

【问题讨论】:

  • 我在这里遇到了与 Android 4+ 相同的问题。从 AsyncTask 启动的 AndroidHttpClient 在发出 POST 请求时永远不会从 execute() 返回。为了让它永远阻塞,我有以下请求序列:POST(500),GET(200),POST(永不结束)
  • 貌似是没有关闭HttpEntity的问题:stackoverflow.com/a/14088063

标签: android


【解决方案1】:

我正在成功使用 POST HTTP 请求。这是我的代码。我使用处理程序删除了显示消息等的部分以及处理程序本身。 POST 字符串类似于“&NAME=value@NAME2=value2”...

protected class ConnectingThread implements Runnable
{          
    Message msg;
    private Handler mExtHandler;
    private String mData;
    private String mUrl;

    /** 
     * @param h (Handler) - a handler for messages from this thread
     * @param data (String) - data to be send in HTTP request's POST
     * @param url (String) - URL to which to connect
     */
    ConnectingThread(Handler h, String data, String url) {
        mExtHandler = h;
        mData = data;
        mUrl = url;
    }

    public void run() {         
        try {
            // TODO use the handler to display txt info about connection

            URL url = new URL(mUrl);
            URLConnection conn = url.openConnection();             
            conn.setConnectTimeout(CONN_TIMEOUT_MILLIS);

            conn.setDoOutput(true);
            BufferedOutputStream wr = new BufferedOutputStream(conn.getOutputStream());                
            wr.write(mData.getBytes());
            wr.flush();
            wr.close();

            String sReturn = null;

            BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            int length = conn.getContentLength();
            char[] buffer = new char[length];
            int read = rd.read(buffer);
            if(read == length)
                sReturn = new String(buffer);
            rd.close();
            buffer = null;   
         // TODO use the handler to use the response

        } catch (Exception e) {
            //....
        }  
        // TODO use the handler to display txt info about connection ERROR   
    }

}           

【讨论】:

  • 这样你就无法访问 HTTP 标头,我需要检查 HTTP 状态码并添加一些特殊的标头。
【解决方案2】:

client.execute(httppost); 不是同步的吗?

你可能需要把它放在一个线程中,否则它会冻结 UI。

【讨论】:

  • 另外,如果我在它分离的线程中运行它会冻结,我永远不会得到响应。唯一的方法是在旧版本的 SDK 中使用 2.2 的 AndroidHttpClient 源代码。
  • 我有类似的问题。但对我来说,在成功执行几次后,execute 方法似乎冻结了。 HttpParams 超时设置最初有效,但后来它只是冻结。
【解决方案3】:

是的,它被冻结只是因为 您还没有将其实现为异步进程。因为当它发出 Web 请求时,您的 UI 将等待响应,然后在收到响应后更新它。

所以这应该作为异步过程来实现,并且应该通知用户(通过进度条或进度对话框)有事情发生。

现在,在 android 中最好并推荐使用 AsyncTask,而不是实现 Runnable 类,它也被称为 Painless Threading

  • 您是否在 doInBackground() 方法中执行后台任务。
  • onPostExecute() 方法中执行显示类型的操作,例如使用获取的数据更新列表视图,在 TextViews 中显示值...等。
  • onPreExecute() 方法中显示 ProgressBar 或 ProgressDialog。

【讨论】:

  • 不,这不是问题,这与已经存在的回复相同。如果我在单独的线程中运行它,它会完全冻结它意味着永远不会结束。
【解决方案4】:

使用AndroidHttpClient 在这种情况下帮助了我。

但现在完整的 AndroidHttpClientDefaultHttpClient 在当前版本的 Android 中已过时,因此现在并不重要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-24
    • 1970-01-01
    • 2012-10-06
    • 2018-04-25
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    相关资源
    最近更新 更多