2016-05-19 3 views
2

Мое приложение использует SQLiteDatabase для сохранения двух массивов для разделения таблиц.Обновление базы данных в фоновой задаче (Android)

Я заметил, что с момента внедрения базы данных, когда она обновляет базу данных (включая удаление таблиц, воссоздание их, а затем их заполнение с помощью arraylists), приложение быстро зависает, и я получаю следующее сообщение в logcat: «I/Хореограф: пропущено 236 кадров! Приложение может делать слишком много работы над своей основной нитью ».

Чтобы подтвердить, что это было обновление, я удалил код, используемый для обновления базы данных. После этого я больше не получил предупреждающее сообщение, и мое приложение не замерзало.

Это код внутри моего пользовательского DB помощника, который простирается SQLiteOpenHelper, который используется для обновления таблицы:

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); 
    } 
} 

И это код, используемый для очистки таблицы, прежде чем они будут обновлены:

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$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>() { 

Edit2: Установленный выше проблемы. Мое приложение вызывало метод вставки данных с использованием пустых списков. Поэтому я добавил нечеткую проверку перед методом вставки данных.

+0

Вы можете показать коды своей деятельности для вас? –

+0

Вы имеете в виду код, используемый классом Activity для доступа к базе данных? – Isengrim

ответ

2

Задача async звучит как хорошая идея.

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(); 


} 
+0

Это что-то довольно легко узнать, как использовать? В основном это приложение, которое я делаю для курсовой работы, поэтому я немного ограничен временем. – Isengrim

+0

Это в значительной степени сделано для вас. Если он выйдет из stacktrace, и я могу помочь вам разобраться. –

+0

Кажется, все работает нормально. У меня проблема с закрытием моей базы данных. Обычно я закрываю базы данных, когда действие приостанавливается, но теперь это похоже на то, что insertData вызывает попытку доступа к закрытой базе данных, даже если я проверю db.isOpen в инструкции if перед вызовом insertData. Также это предупреждение отображается над методами doInBackground «Непосредственное создание массива генериков для параметра varargs». – Isengrim