在后台更新数据库任务 (Android)
Updating Database in Background task (Android)
我的应用程序使用 SQLiteDatabase 来保存两个数组列表以分隔 tables。
我注意到,自从实施数据库以来,每当它更新数据库(涉及删除 tables,重新创建它们,然后用数组列表填充它们)时,应用程序都会短暂地冻结,我收到以下消息在 logcat 中:
"I/Choreographer: Skipped 236 frames! The application may be doing too much work on its main thread."
为了确认是更新,我删除了用于更新数据库的代码。这样做后,我不再收到警告消息,我的应用程序也没有冻结。
这是我的自定义数据库助手中的代码,它扩展了 SQLiteOpenHelper,用于更新 table:
public void insertData(ArrayList<SavedWifiHotspot> hotspots, ArrayList<MarkerOptions> markers) {
Log.d("insert LocationsDB", "Data inserted");
SQLiteDatabase db = this.getWritableDatabase();
ContentValues hotspotValues = new ContentValues();
ContentValues markerValues = new ContentValues();
for(SavedWifiHotspot hotspot : hotspots) {
hotspotValues.put("Ssid", hotspot.getSsid());
hotspotValues.put("Password", hotspot.getPassword());
hotspotValues.put("LocationName", hotspot.getHotspotLoc());
hotspotValues.put("Lat", hotspot.getLatitude());
hotspotValues.put("Lng", hotspot.getLongitude());
db.insert(HOTSPOT_TABLE_NAME, null, hotspotValues);
}
for(MarkerOptions marker : markers) {
markerValues.put("LocationName", marker.getTitle());
markerValues.put("Lat", marker.getPosition().latitude);
markerValues.put("Lng", marker.getPosition().longitude);
db.insert(LOCATION_TABLE_NAME, null, markerValues);
}
}
这是用于在更新之前清除 table 的代码:
public void clearData() {
Log.d("clear LocationsDB", "Tables cleared");
SQLiteDatabase db=this.getWritableDatabase();
String dropHSTable = "DROP TABLE IF EXISTS "
+ HOTSPOT_TABLE_NAME + ";";
String dropLocTable = "DROP TABLE IF EXISTS "
+ LOCATION_TABLE_NAME + ";";
db.execSQL(dropHSTable);
db.execSQL(dropLocTable);
createTables(db);
}
我应该如何在后台更新我的数据库?我读过有关线程的内容,我应该使用线程来执行此操作吗?
编辑:这是错误,参考了我的评论。
FATAL EXCEPTION: AsyncTask #5
Process: com1032.cw2.fm00232.fm00232_assignment2, PID: 8830
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExe
at java.lang.Thread.run(Thread.java:818)cutor$Worker.run(ThreadPoolExecutor.java:587)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB.doInBackground(LocationsDB.java:124)
at at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB.doInBackground(LocationsDB.java:119)
at android.os.AsyncTask.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
作为参考,第 124 行是:
for(MarkerOptions marker: markers[0]) {
而第 119 行是:
new AsyncTask<ArrayList<MarkerOptions>, Void, Void>() {
Edit2:修复了上述问题。我的应用程序使用空列表调用插入数据方法。所以我在插入数据方法之前添加了 .empty 检查。
异步任务听起来是个好主意。
public void insertData(ArrayList<SavedWifiHotspot> hotspots, ArrayList<MarkerOptions> markers) {
Log.d("insert LocationsDB", "Data inserted");
new AsyncTask<ArrayList<SavedWifiHotspot>, Void, Void>() {
@Override
protected Void doInBackground(ArrayList<SavedWifiHotspot>... hotspots) {
ContentValues hotspotValues = new ContentValues();
for(SavedWifiHotspot hotspot : hotspots[0]) {
hotspotValues.put("Ssid", hotspot.getSsid());
hotspotValues.put("Password", hotspot.getPassword());
hotspotValues.put("LocationName", hotspot.getHotspotLoc());
hotspotValues.put("Lat", hotspot.getLatitude());
hotspotValues.put("Lng", hotspot.getLongitude());
db.insert(HOTSPOT_TABLE_NAME, null, hotspotValues);
}
}
}.execute(hotspots);
new AsyncTask<ArrayList<MarkerOptions>, Void, Void>() {
@Override
protected Void doInBackground(ArrayList<MarkerOptions>... options) {
ContentValues hotspotValues = new ContentValues();
for(MarkerOptions marker: options[0]) {
markerValues.put("LocationName", marker.getTitle());
markerValues.put("Lat", marker.getPosition().latitude);
markerValues.put("Lng", marker.getPosition().longitude);
db.insert(LOCATION_TABLE_NAME, null, markerValues);
}
}
}.execute(options);
}
public void clearData() {
Log.d("clear LocationsDB", "Tables cleared");
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SQLiteDatabase db=this.getWritableDatabase();
String dropHSTable = "DROP TABLE IF EXISTS "
+ HOTSPOT_TABLE_NAME + ";";
String dropLocTable = "DROP TABLE IF EXISTS "
+ LOCATION_TABLE_NAME + ";";
db.execSQL(dropHSTable);
db.execSQL(dropLocTable);
createTables(db);
}
}.execute();
}
我的应用程序使用 SQLiteDatabase 来保存两个数组列表以分隔 tables。
我注意到,自从实施数据库以来,每当它更新数据库(涉及删除 tables,重新创建它们,然后用数组列表填充它们)时,应用程序都会短暂地冻结,我收到以下消息在 logcat 中: "I/Choreographer: Skipped 236 frames! The application may be doing too much work on its main thread."
为了确认是更新,我删除了用于更新数据库的代码。这样做后,我不再收到警告消息,我的应用程序也没有冻结。
这是我的自定义数据库助手中的代码,它扩展了 SQLiteOpenHelper,用于更新 table:
public void insertData(ArrayList<SavedWifiHotspot> hotspots, ArrayList<MarkerOptions> markers) {
Log.d("insert LocationsDB", "Data inserted");
SQLiteDatabase db = this.getWritableDatabase();
ContentValues hotspotValues = new ContentValues();
ContentValues markerValues = new ContentValues();
for(SavedWifiHotspot hotspot : hotspots) {
hotspotValues.put("Ssid", hotspot.getSsid());
hotspotValues.put("Password", hotspot.getPassword());
hotspotValues.put("LocationName", hotspot.getHotspotLoc());
hotspotValues.put("Lat", hotspot.getLatitude());
hotspotValues.put("Lng", hotspot.getLongitude());
db.insert(HOTSPOT_TABLE_NAME, null, hotspotValues);
}
for(MarkerOptions marker : markers) {
markerValues.put("LocationName", marker.getTitle());
markerValues.put("Lat", marker.getPosition().latitude);
markerValues.put("Lng", marker.getPosition().longitude);
db.insert(LOCATION_TABLE_NAME, null, markerValues);
}
}
这是用于在更新之前清除 table 的代码:
public void clearData() {
Log.d("clear LocationsDB", "Tables cleared");
SQLiteDatabase db=this.getWritableDatabase();
String dropHSTable = "DROP TABLE IF EXISTS "
+ HOTSPOT_TABLE_NAME + ";";
String dropLocTable = "DROP TABLE IF EXISTS "
+ LOCATION_TABLE_NAME + ";";
db.execSQL(dropHSTable);
db.execSQL(dropLocTable);
createTables(db);
}
我应该如何在后台更新我的数据库?我读过有关线程的内容,我应该使用线程来执行此操作吗?
编辑:这是错误,参考了我的评论。
FATAL EXCEPTION: AsyncTask #5
Process: com1032.cw2.fm00232.fm00232_assignment2, PID: 8830
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExe
at java.lang.Thread.run(Thread.java:818)cutor$Worker.run(ThreadPoolExecutor.java:587)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB.doInBackground(LocationsDB.java:124)
at at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB.doInBackground(LocationsDB.java:119)
at android.os.AsyncTask.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
作为参考,第 124 行是:
for(MarkerOptions marker: markers[0]) {
而第 119 行是:
new AsyncTask<ArrayList<MarkerOptions>, Void, Void>() {
Edit2:修复了上述问题。我的应用程序使用空列表调用插入数据方法。所以我在插入数据方法之前添加了 .empty 检查。
异步任务听起来是个好主意。
public void insertData(ArrayList<SavedWifiHotspot> hotspots, ArrayList<MarkerOptions> markers) {
Log.d("insert LocationsDB", "Data inserted");
new AsyncTask<ArrayList<SavedWifiHotspot>, Void, Void>() {
@Override
protected Void doInBackground(ArrayList<SavedWifiHotspot>... hotspots) {
ContentValues hotspotValues = new ContentValues();
for(SavedWifiHotspot hotspot : hotspots[0]) {
hotspotValues.put("Ssid", hotspot.getSsid());
hotspotValues.put("Password", hotspot.getPassword());
hotspotValues.put("LocationName", hotspot.getHotspotLoc());
hotspotValues.put("Lat", hotspot.getLatitude());
hotspotValues.put("Lng", hotspot.getLongitude());
db.insert(HOTSPOT_TABLE_NAME, null, hotspotValues);
}
}
}.execute(hotspots);
new AsyncTask<ArrayList<MarkerOptions>, Void, Void>() {
@Override
protected Void doInBackground(ArrayList<MarkerOptions>... options) {
ContentValues hotspotValues = new ContentValues();
for(MarkerOptions marker: options[0]) {
markerValues.put("LocationName", marker.getTitle());
markerValues.put("Lat", marker.getPosition().latitude);
markerValues.put("Lng", marker.getPosition().longitude);
db.insert(LOCATION_TABLE_NAME, null, markerValues);
}
}
}.execute(options);
}
public void clearData() {
Log.d("clear LocationsDB", "Tables cleared");
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
SQLiteDatabase db=this.getWritableDatabase();
String dropHSTable = "DROP TABLE IF EXISTS "
+ HOTSPOT_TABLE_NAME + ";";
String dropLocTable = "DROP TABLE IF EXISTS "
+ LOCATION_TABLE_NAME + ";";
db.execSQL(dropHSTable);
db.execSQL(dropLocTable);
createTables(db);
}
}.execute();
}