繁体   English   中英

在AsyncTask中打开SQLiteDatabase数据库(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();
    }

如果locDB.clearData(); 也是异步的,它可以通过使用locDB.insertDatalocDB.insertData打开与同一SQLite数据库的连接来导致该错误。

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

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

您必须先不使用WAL(预先写入日志记录),才能在SQLite上同时执行读写操作。 请遵循以下详细信息SQLite数据库中的并发

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM