我正在开发我的第一个应用程序并创建以下连接到远程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;
}
答案 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.
将此代码放在最后。