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



我正在开发我的第一个应用程序,我创建了以下方法,该方法连接到远程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;
}   

需要考虑的几件事:

  • 套接字和HTTP连接超时

    首先,修改您的HTTP连接以使连接和套接字超时

        BasicHttpParams basicParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout( basicParams, timeout * 1000 );
        HttpConnectionParams.setSoTimeout( basicParams, timeout * 1000 );
        DefaultHttpClient client = new DefaultHttpClient( basicParams );
    
  • 在超时时优雅地退出您的挂起请求

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

    • 我假设您已经在一个单独的线程中调用了这个storeData,我建议您使用AsyncTask,因为我们可以在超时时调用它的cancel方法。您的storeData代码将在asyncTask的doInBackground中,并且在读取实体响应数据的"while"循环中,您可以检查asyncTask的isCancelled并优雅地关闭

      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);

使用这样的处理程序-

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.

把这个代码放在最后。

相关内容

  • 没有找到相关文章

最新更新