在新线程中将值插入数据库会导致进度对话框消失
Inserting values to database in new thread causes progress dialog to dissmiss
在我的应用程序中,我从服务器下载了大量数据(大约 3000-4000 条记录),然后将其插入数据库。这个过程需要很长时间,所以我想在整个过程运行时显示进度对话框。我在 AsyncTask class 中实现了进度对话框,我正在其中下载数据并将其插入数据库。这是 AsyncTask 的代码:
@Override
protected void onPreExecute() {
super.onPreExecute();
a.runOnUiThread(new Runnable(){
@Override
public void run() {
pd.setTitle("Загрузка необходимых данных");
pd.setMessage("Пожалуйста подождите");
pd.setIndeterminate(true);
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.setProgress(0);
pd.setCancelable(false);
pd.show();
}
});
}
protected Map<String, String> doInBackground(String... strs) {
return getMaterials();
}
@Override
protected void onPostExecute (Map<String, String> map) {
a.runOnUiThread(new Runnable(){
@Override
public void run() {
pd.dismiss();
}
});
}
public Map<String,String> getMaterials() {
int maxNum = getMaxIndex("materials");
Map<String,String> materials = null;
DBConnection db = new DBConnection(context);
Date end = new Date(System.currentTimeMillis());
String exml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
"<REQUEST format=\"json\" client=\"exstroy\" action=\"get\" enddate=\""+ end.toString() + "\" " +
"startdate=\"2000-01-28\" POINT_ID=\"3\" session=\"" + session_id + "\" catalogname=\"nomenclature\" type=\"cataloglist\">" +
"<LIST firstmrid = \"0\" lastmrid=\""+ maxNum + "\"></LIST>" +
"</REQUEST>";
try{
PrintWriter writer = new PrintWriter(Environment.getExternalStorageDirectory().getPath() + "/data.xml", "UTF-8");
writer.println(exml);
writer.close();
} catch (IOException e) {
}
String charset = "UTF-8";
File uploadFile1 = new File(Environment.getExternalStorageDirectory().getPath() + "/data.xml");
String requestURL = "blahblah.com";
try {
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
multipart.addFilePart("datafile", uploadFile1);
List<String> response = multipart.finish();
materials = new HashMap<String, String>();
String s = "{ " + response.get(1) + "}";
JSONObject json = new JSONObject(s);
JSONObject cataloglist = json.getJSONObject("cataloglist");
JSONArray array = cataloglist.names();
//db.clearNomenclature();
ArrayList<Map<String, Object>> data = new ArrayList<Map<String, Object>>(5000);
int max = 0;
for(int n = 0; n < array.length(); n++)
{
if (n > max)
max = n;
JSONObject object = cataloglist.getJSONObject(array.getString(n));
Map<String, Object> map;
map = new HashMap<String, Object>();
if (object.has("version"))
map.put("version", object.getInt("version"));
else
map.put("version", 0);
if (object.has("name"))
map.put("name", object.getString("name"));
else
map.put("name", "");
if (object.has("uuid"))
map.put("uuid", object.getString("uuid"));
else
map.put("uuid", "");
if (object.has("uuid"))
map.put("measure", object.getString("measure"));
else
map.put("measure", "");
data.add(map);
}
db.insertNom(data);
} catch (IOException ex) {
System.err.println(ex);
} catch (JSONException e) {
e.printStackTrace();
}
ArrayList<Map<String, String>> measures = getMeasures();
db.measures(measures);
return materials;
}
在执行下载数据时显示进度对话框,但当它到达数据库插入进度对话框时关闭。这是数据库插入的代码部分:
public void insertNom(final ArrayList<Map<String, Object>> data) {
dbOpen();
database.execSQL("CREATE TABLE IF NOT EXISTS "+"nomenclature"+
" ("+"ID"+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
"name TEXT, version INTEGER, measure UUID, uuid UUID)");
dbClose();
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < data.size(); i++) {
dbOpen();
Map<String, Object> map = data.get(i);
ContentValues cv = new ContentValues();
cv.put("name", (String) map.get("name"));
cv.put("version", (int) map.get("version"));
cv.put("uuid", (String) map.get("uuid"));
cv.put("measure", (String) map.get("measure"));
database.insert("nomenclature", null, cv);
dbClose();
}
}
};
new Thread(runnable).start();
}
正如您在上面的代码中看到的那样,我尝试在单独的线程中执行此操作,我也尝试仅在 AsyncTask 的 doInBackgroung 方法中执行此操作。两种方式都关闭了进度对话框。另外还有一个问题,虽然从服务器下载数据比较快:3-4秒,插入数据库大约需要20秒,甚至更多。有什么办法可以更快吗?如果不是,是什么导致进度对话框关闭?
您不需要另一个可运行线程来执行您的数据库插入,因为它已经在 AsyncTask
的 doInBackground()
中,它是 运行 在后台线程中。
删除 Runnable 块:
//Runnable runnable = new Runnable() {
// @Override
// public void run() {
for (int i = 0; i < data.size(); i++) {
dbOpen();
Map<String, Object> map = data.get(i);
ContentValues cv = new ContentValues();
cv.put("name", (String) map.get("name"));
cv.put("version", (int) map.get("version"));
cv.put("uuid", (String) map.get("uuid"));
cv.put("measure", (String) map.get("measure"));
database.insert("nomenclature", null, cv);
dbClose();
}
// }
// };
// new Thread(runnable).start();
希望这有效!
需要在 table 中插入大约 3000-4000 条记录。执行以下更改以加快插入速度:
1. 如果数据直接从JSON插入到table那么不需要在[=11=中保存JSON对象].只需使用 JsonReader
即可读取 JSON 编码值作为令牌流。并为每个对象调用插入方法。 (可选,但如果您在当前代码中这样做,那么它也会减少读取和打包集合中数据的时间)
2. 仅使用 doInBackground
并从 insertNom
方法中删除线程。
3. 在 doInBackground
中使用 Android 数据库事务进行批量插入。喜欢:
protected Map<String, String> doInBackground(String... strs) {
// 1. Open DB
// 2. Create Table
Map<String, String> materials=getMaterials();
// 3.
// START Transaction
database.beginTransaction();
//call insertNom method
insertNom(materials);
// set Successful
database.setTransactionSuccessful();
// END Transaction
database.endTransaction();
return materials;
}
在我的应用程序中,我从服务器下载了大量数据(大约 3000-4000 条记录),然后将其插入数据库。这个过程需要很长时间,所以我想在整个过程运行时显示进度对话框。我在 AsyncTask class 中实现了进度对话框,我正在其中下载数据并将其插入数据库。这是 AsyncTask 的代码:
@Override
protected void onPreExecute() {
super.onPreExecute();
a.runOnUiThread(new Runnable(){
@Override
public void run() {
pd.setTitle("Загрузка необходимых данных");
pd.setMessage("Пожалуйста подождите");
pd.setIndeterminate(true);
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.setProgress(0);
pd.setCancelable(false);
pd.show();
}
});
}
protected Map<String, String> doInBackground(String... strs) {
return getMaterials();
}
@Override
protected void onPostExecute (Map<String, String> map) {
a.runOnUiThread(new Runnable(){
@Override
public void run() {
pd.dismiss();
}
});
}
public Map<String,String> getMaterials() {
int maxNum = getMaxIndex("materials");
Map<String,String> materials = null;
DBConnection db = new DBConnection(context);
Date end = new Date(System.currentTimeMillis());
String exml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
"<REQUEST format=\"json\" client=\"exstroy\" action=\"get\" enddate=\""+ end.toString() + "\" " +
"startdate=\"2000-01-28\" POINT_ID=\"3\" session=\"" + session_id + "\" catalogname=\"nomenclature\" type=\"cataloglist\">" +
"<LIST firstmrid = \"0\" lastmrid=\""+ maxNum + "\"></LIST>" +
"</REQUEST>";
try{
PrintWriter writer = new PrintWriter(Environment.getExternalStorageDirectory().getPath() + "/data.xml", "UTF-8");
writer.println(exml);
writer.close();
} catch (IOException e) {
}
String charset = "UTF-8";
File uploadFile1 = new File(Environment.getExternalStorageDirectory().getPath() + "/data.xml");
String requestURL = "blahblah.com";
try {
MultipartUtility multipart = new MultipartUtility(requestURL, charset);
multipart.addFilePart("datafile", uploadFile1);
List<String> response = multipart.finish();
materials = new HashMap<String, String>();
String s = "{ " + response.get(1) + "}";
JSONObject json = new JSONObject(s);
JSONObject cataloglist = json.getJSONObject("cataloglist");
JSONArray array = cataloglist.names();
//db.clearNomenclature();
ArrayList<Map<String, Object>> data = new ArrayList<Map<String, Object>>(5000);
int max = 0;
for(int n = 0; n < array.length(); n++)
{
if (n > max)
max = n;
JSONObject object = cataloglist.getJSONObject(array.getString(n));
Map<String, Object> map;
map = new HashMap<String, Object>();
if (object.has("version"))
map.put("version", object.getInt("version"));
else
map.put("version", 0);
if (object.has("name"))
map.put("name", object.getString("name"));
else
map.put("name", "");
if (object.has("uuid"))
map.put("uuid", object.getString("uuid"));
else
map.put("uuid", "");
if (object.has("uuid"))
map.put("measure", object.getString("measure"));
else
map.put("measure", "");
data.add(map);
}
db.insertNom(data);
} catch (IOException ex) {
System.err.println(ex);
} catch (JSONException e) {
e.printStackTrace();
}
ArrayList<Map<String, String>> measures = getMeasures();
db.measures(measures);
return materials;
}
在执行下载数据时显示进度对话框,但当它到达数据库插入进度对话框时关闭。这是数据库插入的代码部分:
public void insertNom(final ArrayList<Map<String, Object>> data) {
dbOpen();
database.execSQL("CREATE TABLE IF NOT EXISTS "+"nomenclature"+
" ("+"ID"+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
"name TEXT, version INTEGER, measure UUID, uuid UUID)");
dbClose();
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < data.size(); i++) {
dbOpen();
Map<String, Object> map = data.get(i);
ContentValues cv = new ContentValues();
cv.put("name", (String) map.get("name"));
cv.put("version", (int) map.get("version"));
cv.put("uuid", (String) map.get("uuid"));
cv.put("measure", (String) map.get("measure"));
database.insert("nomenclature", null, cv);
dbClose();
}
}
};
new Thread(runnable).start();
}
正如您在上面的代码中看到的那样,我尝试在单独的线程中执行此操作,我也尝试仅在 AsyncTask 的 doInBackgroung 方法中执行此操作。两种方式都关闭了进度对话框。另外还有一个问题,虽然从服务器下载数据比较快:3-4秒,插入数据库大约需要20秒,甚至更多。有什么办法可以更快吗?如果不是,是什么导致进度对话框关闭?
您不需要另一个可运行线程来执行您的数据库插入,因为它已经在 AsyncTask
的 doInBackground()
中,它是 运行 在后台线程中。
删除 Runnable 块:
//Runnable runnable = new Runnable() {
// @Override
// public void run() {
for (int i = 0; i < data.size(); i++) {
dbOpen();
Map<String, Object> map = data.get(i);
ContentValues cv = new ContentValues();
cv.put("name", (String) map.get("name"));
cv.put("version", (int) map.get("version"));
cv.put("uuid", (String) map.get("uuid"));
cv.put("measure", (String) map.get("measure"));
database.insert("nomenclature", null, cv);
dbClose();
}
// }
// };
// new Thread(runnable).start();
希望这有效!
需要在 table 中插入大约 3000-4000 条记录。执行以下更改以加快插入速度:
1. 如果数据直接从JSON插入到table那么不需要在[=11=中保存JSON对象].只需使用 JsonReader
即可读取 JSON 编码值作为令牌流。并为每个对象调用插入方法。 (可选,但如果您在当前代码中这样做,那么它也会减少读取和打包集合中数据的时间)
2. 仅使用 doInBackground
并从 insertNom
方法中删除线程。
3. 在 doInBackground
中使用 Android 数据库事务进行批量插入。喜欢:
protected Map<String, String> doInBackground(String... strs) {
// 1. Open DB
// 2. Create Table
Map<String, String> materials=getMaterials();
// 3.
// START Transaction
database.beginTransaction();
//call insertNom method
insertNom(materials);
// set Successful
database.setTransactionSuccessful();
// END Transaction
database.endTransaction();
return materials;
}