2016-05-19 52 views
0

当我在关闭数据库后尝试调用它时,我的自定义SQLiteOpenHelper类中的一个方法会引发“尝试重新打开已关闭的对象”错误。我在我的MainActivity的onPause中关闭数据库,然后在调用数据库方法之前确保它们是否打开。SQLiteDatabase在AsyncTask中打开数据库(Android)

这是数据库方法的代码,它在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(); 
    } 
+0

我想你不是在clearData()方法中关闭你的数据库,然后在insertData()方法中再次打开它。 –

+0

数据库未在clearData()中关闭。在我的onPause方法中,我调用updateLocDB(),然后关闭数据库。 – Isengrim

+0

看到答案,希望这会帮助你。 –

回答

0

根据我的理解,您在同一时间执行两个异步任务。并在两个任务中创建/打开SQLite数据库连接。这造成了问题。

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

您不能在SQLite上同时执行读取和写入操作,直到您不使用WAL(预写日志记录)。按照这个更多的信息Concurrency in SQLite database

+0

谢谢,我会看看实现一个ContentProvider。这似乎是我需要的。 – Isengrim

0

如果locDB.clearData();也是异步它可以通过具有连接打开以与locDB.insertDatalocDB.insertData相同SQLite数据库会导致错误。

+0

它也是异步,我已经包含它的代码。但是,执行clearData时该应用程序已经崩溃。同样与insertData。我将代码更改为仅在updateDB中执行insertData,并且出于同样的原因它仍然崩溃。 – Isengrim