SQLiteDatabase在AsyncTask(Android)中打开数据库(SQLiteDatabase Opening DB in AsyncTask (Android))

编程入门 行业动态 更新时间:2024-10-23 07:26:16
SQLiteDatabase在AsyncTask(Android)中打开数据库(SQLiteDatabase Opening DB in AsyncTask (Android))

在我关闭数据库时尝试调用它时,我的自定义SQLiteOpenHelper类中的一个方法会抛出“尝试重新打开已关闭的对象”错误。 我在MainActivity上关闭onPause中的数据库,然后确保在调用数据库上的方法之前检查它们是否已打开。

这是数据库方法的代码,它位于AsyncTask中。

public void insertData(ArrayList<SavedWifiHotspot> hotspots, ArrayList<MarkerOptions> markers) { Log.d("insert LocationsDB", "Data inserted"); final SQLiteDatabase db = this.getWritableDatabase(); new AsyncTask<ArrayList<SavedWifiHotspot>, Void, Void>() { @Override protected Void doInBackground(ArrayList<SavedWifiHotspot>... hotspots) { Log.d("insert LocationsDB", "Hotspot inserted"); 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); } return null; } }.execute(hotspots); new AsyncTask<ArrayList<MarkerOptions>, Void, Void>() { @Override protected Void doInBackground(ArrayList<MarkerOptions>... markers) { ContentValues markerValues = new ContentValues(); for(MarkerOptions marker: markers[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); } return null; } }.execute(markers); }

这是用于调用方法的代码:

public void updateLocDB() { if(!db.isOpen()) { db = locDB.getReadableDatabase(); } if(!wifiHotspots.isEmpty() && !markers.isEmpty()) { locDB.clearData(); locDB.insertData(wifiHotspots, markers); } }

Logcat输出:

FATAL EXCEPTION: AsyncTask #1 Process: com1032.cw2.fm00232.fm00232_assignment2, PID: 368 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.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818) Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:/data/data/com1032.cw2.fm00232.fm00232_assignment2/databases/locationsDB at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1659) at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605) at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$1.doInBackground(LocationsDB.java:89) at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$1.doInBackground(LocationsDB.java:75) 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)

我一直在寻找几个小时,找不到任何可以帮我解决这个问题的方法。 任何帮助,将不胜感激。

clearData代码:

public void clearData() { Log.d("clear LocationsDB", "Tables cleared"); db = this.getReadableDatabase(); new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { 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); return null; } }.execute(); }

One of my methods in my custom SQLiteOpenHelper class throws an "attempt to re-open already closed object" error whenever I try to invoke it after closing the database. I close my databases in onPause on my MainActivity, and then I make sure to check if they are open before invoking a method on the database.

This is the code for the database method, it is within an AsyncTask.

public void insertData(ArrayList<SavedWifiHotspot> hotspots, ArrayList<MarkerOptions> markers) { Log.d("insert LocationsDB", "Data inserted"); final SQLiteDatabase db = this.getWritableDatabase(); new AsyncTask<ArrayList<SavedWifiHotspot>, Void, Void>() { @Override protected Void doInBackground(ArrayList<SavedWifiHotspot>... hotspots) { Log.d("insert LocationsDB", "Hotspot inserted"); 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); } return null; } }.execute(hotspots); new AsyncTask<ArrayList<MarkerOptions>, Void, Void>() { @Override protected Void doInBackground(ArrayList<MarkerOptions>... markers) { ContentValues markerValues = new ContentValues(); for(MarkerOptions marker: markers[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); } return null; } }.execute(markers); }

This is the code used to call the method:

public void updateLocDB() { if(!db.isOpen()) { db = locDB.getReadableDatabase(); } if(!wifiHotspots.isEmpty() && !markers.isEmpty()) { locDB.clearData(); locDB.insertData(wifiHotspots, markers); } }

Logcat output:

FATAL EXCEPTION: AsyncTask #1 Process: com1032.cw2.fm00232.fm00232_assignment2, PID: 368 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.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818) Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:/data/data/com1032.cw2.fm00232.fm00232_assignment2/databases/locationsDB at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1659) at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605) at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$1.doInBackground(LocationsDB.java:89) at com1032.cw2.fm00232.fm00232_assignment2.LocationsDB$1.doInBackground(LocationsDB.java:75) 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)

I've been searching for a few hours, and can't find anything that helps me fix this problem. Any help would be appreciated.

clearData code:

public void clearData() { Log.d("clear LocationsDB", "Tables cleared"); db = this.getReadableDatabase(); new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { 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); return null; } }.execute(); }

最满意答案

根据我的理解,您正在同时执行两个异步任务。 并在两个任务中创建/打开SQLite DB连接。 这就产生了问题。

因为,无法创建两个SQLite DB连接。 因为SQLite是ThreadSafe,所以一次只能有一个线程执行读/写操作。

在不使用WAL(Write Ahead Logging)之前,不能在SQLite上同时执行读写操作。 请关注此以获取更多信息SQLite数据库中的并发

As per my understanding you are executing two asynchronous task at same time. And creating/opening a SQLite DB connection in both tasks. Which creates the problem.

As, it is not possible to create two connections of SQLite DB. Because SQLite is ThreadSafe, only one thread can perform read/write operation at a single time.

You can not perform read and write operations concurrently on SQLite until you do not use WAL(Write Ahead Logging). Follow this for more info Concurrency in SQLite database

更多推荐

本文发布于:2023-07-28 01:14:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1298266.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数据库   AsyncTask   SQLiteDatabase   Android   DB

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!