2014-10-09 74 views
0

我正在開發我的第一個應用程序,並且我創建了以下連接到遠程URL的方法,獲取JSON文件並將其寫入本地SQLite數據庫。有時會發生互聯網連接緩慢或不良,我會設置一個計時器。例如,如果3秒後它不會得到JSON文件,我會拋出AlertDialog讓用戶選擇是否重試或取消。那麼如何給我的函數添加超時?如何在Android中添加HttpClient請求和連接超時

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; 
} 
+0

@ashoke大型傳輸比其他任何類型的傳輸都更不可能。一些新數據在每次讀取的超時時間內到達,否則不會。但是,這個單一的陳述是唯一錯誤的,否則你的優秀和正確的答案。我已投票拒絕刪除它。 – EJP 2014-10-10 23:21:25

+0

我還沒有解決...我會再次看到你的答案...如何做到這一點? – smartmouse 2014-10-11 07:52:37

+0

@EJP我只是指出我們需要一種方式來取消大型轉移中。 'smartmouse',我沒有刪除看到下面 – ashoke 2014-10-11 18:44:28

回答

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. 

將這個代碼的結束。

+0

我正在使用這個解決方案...爲什麼有人downvote它呢?怎麼了? – smartmouse 2014-10-10 10:47:03

+0

我不知道。它實際上工作... – Confuse 2014-10-10 11:00:07

+0

這不是必要的,那是什麼錯。套接字已經直接支持超時。見@ ashoke的答案。不需要額外的線程。 – EJP 2014-10-10 23:17:41

1

幾件事情要考慮:

  • 套接字和HTTP連接超時

    首先,修改你的HTTP連接,必須連接插座超時

    BasicHttpParams basicParams = new BasicHttpParams(); 
        HttpConnectionParams.setConnectionTimeout(basicParams, timeout * 1000); 
        HttpConnectionParams.setSoTimeout(basicParams, timeout * 1000); 
        DefaultHttpClient client = new DefaultHttpClient(basicParams); 
    
  • 退出您的待處理請求優雅uest對超時

    • 您可以慢速連接運行的時間,如果響應數據是大的,在這種情況下,我們需要正常關閉HttpClient的資源。我建議你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建議的簡單延遲handlerrunnable

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

+0

響應的大小與超時的概率無關。 – EJP 2014-10-10 08:01:53

+0

@EJP問題提到連接速度慢或用戶想提前取消 – ashoke 2014-10-10 08:04:13

+0

如果3G信號突然掉下來或用戶在下載過程中禁用WiFi,該代碼是否可以管理? – smartmouse 2014-10-12 08:19:57