如何在Android中添加HttpClient请求和连接超时

时间:2014-10-09 23:49:59

标签: android sockets http connection timeout

我正在开发我的第一个应用程序并创建以下连接到远程URL的方法,获取JSON文件并将其写入本地SQLite数据库。有时会发生互联网连接缓慢或坏的情况,我会设置一个计时器。例如,如果3秒后它没有获得JSON文件,我会抛出一个AlertDialog,让用户选择是否重试或取消。那么如何为我的函数添加超时?

public int storeData(Database db, int num) throws JSONException {

    HttpClient client = new DefaultHttpClient();
    HttpGet request = new HttpGet("http://www.example.com/file.json");
    request.addHeader("Cache-Control", "no-cache");
    long id = -1;

    try {
        HttpResponse response = client.execute(request);
        HttpEntity entity = response.getEntity();
        InputStreamReader in = new InputStreamReader(entity.getContent());
        BufferedReader reader = new BufferedReader(in);
        StringBuilder stringBuilder = new StringBuilder();
        String line = "";

        while ((line=reader.readLine()) != null) {
            stringBuilder.append(line);
        }

        JSONArray jsonArray = new JSONArray(stringBuilder.toString());
        SQLiteDatabase dbWrite = db.getWritableDatabase();
        ContentValues values = new ContentValues();
        if (jsonArray.length() == num && num != 0)
            return num;
        SQLiteDatabase dbread = db.getReadableDatabase();

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jObj = (JSONObject) jsonArray.getJSONObject(i);

            values.put("id", jObj.optString("id").toString());
            values.put("name", jObj.optString("firstname").toString());
            values.put("surname",jObj.optString("lastname").toString());

            id = dbWrite.insert("users", null, values);
        }
        num = jsonArray.length();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    if (id > 0)
        return num;
    else
        return -1;
}   

2 个答案:

答案 0 :(得分:1)

很少有事情需要考虑:

  • 套接字和HTTP连接超时

    首先,修改HTTP连接以获得连接和套接字超时

        BasicHttpParams basicParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout( basicParams, timeout * 1000 );
        HttpConnectionParams.setSoTimeout( basicParams, timeout * 1000 );
        DefaultHttpClient client = new DefaultHttpClient( basicParams );
    
  • 在超时时正常退出待处理的请求

    • 如果响应数据很大,您可能会因连接速度慢而耗尽时间,在这种情况下,我们需要优雅地关闭HTTPClient资源。

    • 我假设你已经在一个单独的线程中调用了这个storeData,我建议你use AsyncTask,因为我们可以call its cancel超时方法。您的storeData代码将为in asyncTask's doInBackground,在您阅读实体响应数据的'while`循环中,您可以检查isCancelled of AsyncTask并正常关闭

      if (isCancelled()) {
          EntityUtils.consume(entity);
          client.getConnectionManager().shutdown();
          return -1;
      }
      
    • 在asyncTask的postExecute函数中,您可以设置isDone以指示成功请求,而不会出现任何超时和任何其他UI处理。

      protected void onPostExecute(...) {                
          isDone = true;
      }
      
  • 在主UI线程上安排和处理超时

    以上两个将处理连接超时,数据超时和慢速连接超时。现在,我们需要处理设置超时并从UI管理它。为此,我们可以使用@Neutrino建议的简单延迟handler runnable

            boolean isDone = false;
            StoreDataTask storeDataTask = new StoreDataTask();
            storeDataTask.execute(...)
            new Handler().postDelayed(new Runnable() {
                public void run() {
                    storeDataTask.cancel(false);
                }
            }, timeout * 1000);
            if (isDone) // we have a successful request without timeout
    

    将上述代码段包装在函数中,如果用户想重试,请再次调用它。注意,如果用户不想等待超时并且只是想取消它,你可以随时从你的onCreate或UI线程调用storeDataTask.cancel(false);

答案 1 :(得分:0)

使用像这样的处理程序 -

final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        //Check if JSON file is there
        //This code will be executed after 3 seconds
    }
}, 3000); //Change time here. The time is in milliseconds. 1 sec = 1000 ms.
         //The code above will be executed after given time.

将此代码放在最后。