在后台任务中更新数据库(Android)
我的应用程序使用SQLiteDatabase将两个ArrayList保存到单独的表中 我注意到,自从实现数据库以来,每当它更新数据库(包括删除表、重新创建表,然后用ArrayList填充表)时,应用程序都会短暂冻结,我在logcat中收到以下消息: “I/Choreographer:跳过236帧!应用程序可能在其主线程上做了太多工作。” 为了确认是更新,我删除了用于更新数据库的代码。这样做之后,我不再收到警告信息,我的应用程序也没有冻结 这是自定义DB helper中的代码,它扩展了SQLiteOpenHelper,用于更新表:在后台任务中更新数据库(Android),android,sqlite,android-asynctask,sqliteopenhelper,Android,Sqlite,Android Asynctask,Sqliteopenhelper,我的应用程序使用SQLiteDatabase将两个ArrayList保存到单独的表中 我注意到,自从实现数据库以来,每当它更新数据库(包括删除表、重新创建表,然后用ArrayList填充表)时,应用程序都会短暂冻结,我在logcat中收到以下消息: “I/Choreographer:跳过236帧!应用程序可能在其主线程上做了太多工作。” 为了确认是更新,我删除了用于更新数据库的代码。这样做之后,我不再收到警告信息,我的应用程序也没有冻结 这是自定义DB helper中的代码,它扩展了SQLite
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);
}
}
我应该如何在后台更新我的数据库?我已经读过关于线程的文章,我应该使用线程来做这件事吗
编辑:这是关于我的评论的错误
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$3.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$1.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$3.doInBackground(LocationsDB.java:124)
at at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$3.doInBackground(LocationsDB.java:119)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.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>() {
newasynctask(){
Edit2:修复了上述问题。我的应用程序使用空列表调用插入数据方法。因此,我在插入数据方法之前添加了。空检查。异步任务听起来是个好主意
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();
}
public void insertData(ArrayList热点、ArrayList标记){
Log.d(“插入位置SDB”,“插入数据”);
新建异步任务(){
@凌驾
受保护的Void doInBackground(ArrayList…热点){
ContentValues热点值=新ContentValues();
对于(SavedWifiHotspot热点:热点[0]){
put(“Ssid”,hotspot.getSsid());
hospotvalues.put(“Password”,hospot.getPassword());
put(“LocationName”,hospot.gethospotloc());
hospotvalues.put(“Lat”,hospot.getLatitude());
hospotvalues.put(“Lng”,hospot.getLongitude());
插入(热点\表\名称,null,热点值);
}
}
}.执行(热点);
新建异步任务(){
@凌驾
受保护的Void doInBackground(ArrayList…选项){
ContentValues热点值=新ContentValues();
对于(标记选项标记:选项[0]){
markerValues.put(“LocationName”,marker.getTitle());
markerValues.put(“Lat”,marker.getPosition().lation);
markerValues.put(“Lng”,marker.getPosition().longitude);
db.insert(位置、表格、名称、null、MarkerValue);
}
}
}.执行(期权);
}
public void clearData(){
Log.d(“清除位置SDB”,“清除表格”);
新建异步任务(){
@凌驾
受保护的Void doInBackground(Void…参数){
SQLiteDatabase db=this.getWritableDatabase();
String dropHSTable=“如果存在,则删除表”
+热点_表_名称+“;”;
String dropOctable=“如果存在,则删除表格”
+位置表名称+“;”;
execSQL(dropHSTable);
db.execSQL(八进制);
创建表(db);
}
}.execute();
}
这是一款很容易学会如何使用的应用程序吗?基本上,我制作的这个应用程序是用于课程作业的,所以我的时间有点有限。这对你来说已经差不多了。如果它崩溃,请发布stacktrace,我可以帮你解决问题。看起来效果很好。我在关闭数据库时遇到问题。通常当活动暂停,但这现在似乎会导致insertData尝试访问关闭的数据库,即使在调用insertData之前在if语句中检查us db.isOpen。此外,doInBackground方法“为varargs参数创建未检查的泛型数组”上也会显示此警告。您是否在onResume
方法中打开对数据库的引用?是的,在我的onResume中,我使用if(!db.isOpen())
检查数据库是否打开,如果没有打开,则执行db=locDB.getReadableDatabase()
。你能给我们看一下你的活动类代码吗?你是指活动类用来访问数据库的代码吗?
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();
}