2016-01-13 2 views
1

Я инициализирую экземпляр базы данных в классе asynctask doInBackground(). Экземпляр базы данных и его методы находятся в отдельном классе (тот, который я покажу). Из асинтезы я запускаю другой поток в классе для моего клиента Azure, который в конечном итоге запрашивает класс базы данных для заполнения моего клиента azure db. Возвращаясь к моей asynctask, я снова обращаюсь к db (одновременно как первый запрос), чтобы запросить db для отдельной информации. Кажется, что два курсора, идущие одновременно из отдельных запросов по темам, вызывают у меня проблемы.несколько курсоров в разных потоках, работающих в одной базе данных

Ниже приведены методы класса db, которые используют первый курсор для отправки материала Azure. Эти методы вызывают из отдельного потока, выполняемого в классе Azure. Класс Azure вызывается в классе asynctask. Как вы увидите в logcat, это работает отлично.

public ArrayList<WeatherEvent> GetUnsychedWeatherEvent() { 
    String query = COLUMN_SYNCHED + " = 0 "; 
    Cursor cursor = db.query(TABLE_WEATHER, null, query, null, null, null, null); 

    ArrayList<WeatherEvent> unsychedWeather = new ArrayList<>(); 
    while (cursor.moveToNext()) { 
     unsychedWeather.add(GetWeatherEvent(cursor)); 
    } 
    cursor.close(); 

    return unsychedWeather; 

} 

//get weather event from db for azure 
//TODO: finish populating this 
public WeatherEvent GetWeatherEvent(Cursor cursor) { 
    WeatherEvent wEvent = new WeatherEvent(); 
    wEvent.Latitude = cursor.getDouble(cursor.getColumnIndex(COLUMN_LATITUDE)); 
    wEvent.Longitude = cursor.getDouble(cursor.getColumnIndex(COLUMN_LONGITUDE)); 
    wEvent.CurrTemp = cursor.getString(cursor.getColumnIndex(COLUMN_CURRENT_TEMPERATURES)); 
    wEvent.CurrDesc = cursor.getString(cursor.getColumnIndex(COLUMN_CURRENT_WEATHER_DESCRIPTION)); 
    System.out.println("From DB, current temp: " + wEvent.CurrTemp); 
    try { 
     wEvent.Time = timeStampFormat.parseDateTime(cursor.getString(cursor.getColumnIndex(COLUMN_TIME_STAMP))); 
    } catch (Exception e) { 
     Log.d("GetEvent()", "Error parsing date " + e.toString()); 
    } 

    return wEvent; 
} 

Эти следующие методы взяты из того же класса. Здесь «dailycursor» - это то, что вызывает у меня проблемы. Эти методы вызывают в классе asynctask.

public ArrayList<WeatherEvent> DailyWeatherEvents(ArrayList<WeatherEvent> dailyWeatherEvents) { 
     Log.d("DB Access", "got to dailyweatherevents"); 

    //todo: more specific time query 
    Cursor dailycursor = db.rawQuery("SELECT avg(" + COLUMN_CURRENT_TEMPERATURES + "), " + COLUMN_TIME_STAMP + ", " + 
      "CASE WHEN strftime('%M', " + COLUMN_TIME_STAMP + ") < '30' " + 
      "THEN strftime('%H', " + COLUMN_TIME_STAMP + ") " + 
      "ELSE strftime('%H', " + COLUMN_TIME_STAMP + ", '+1 hours') END " + 
      "FROM " + TABLE_WEATHER + " "+ 
      "GROUP BY strftime('%H', " + COLUMN_TIME_STAMP + ", '+30 minutes')", null); 

    //ArrayList<WeatherEvent> dailyWeatherEvents = new ArrayList<>(); 
    try { 
     if (dailycursor.moveToFirst()) { 
      while (dailycursor.moveToNext()) { 
       dailyWeatherEvents.add(GetDailyWeatherEvent(dailycursor)); 

      } 
      dailycursor.close(); 
      System.out.println("Size of dailyinfo " + dailyWeatherEvents.size()); 
     } 
     } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return dailyWeatherEvents; 
} 

public WeatherEvent GetDailyWeatherEvent(Cursor dailycursor) { 
    WeatherEvent wEvent = new WeatherEvent(); 
    // wEvent.Latitude = dailycursor.getDouble(dailycursor.getColumnIndex(COLUMN_LATITUDE)); 
    // wEvent.Longitude = dailycursor.getDouble(dailycursor.getColumnIndex(COLUMN_LONGITUDE)); 
    wEvent.CurrTemp = dailycursor.getString(dailycursor.getColumnIndex(COLUMN_CURRENT_TEMPERATURES)); 
    System.out.println(wEvent.CurrTemp + " mariah this comes from cursor"); 
    wEvent.CurrDesc = dailycursor.getString(dailycursor.getColumnIndex(COLUMN_CURRENT_WEATHER_DESCRIPTION)); 
    try { 
     wEvent.Time = timeStampFormat.parseDateTime(dailycursor.getString(dailycursor.getColumnIndex(COLUMN_TIME_STAMP))); 
    } catch (Exception e) { 
     Log.d("GetEvent()", "Error parsing date " + e.toString()); 
    } 
    wEvent.CurrIcon = dailycursor.getString(dailycursor.getColumnIndex(COLUMN_CURRENT_ICONS)); 
    wEvent.SevereWeatherPresent = dailycursor.getInt(dailycursor.getColumnIndex(COLUMN_SEVERE_WEATHER_PRESENT))>0; 

    return wEvent; 

} 

Строки из класса asynctask, которые запускают все это. WeatherDBAccess - это класс DB. WeatherAzureAccess это лазурное класс:

WeatherDBAccess._context = this.context; 
      WeatherDBAccess.Instance().AddWeatherEvent(wEvent); 
      //starts azure 
      WeatherAzureAccess.context = this.context; 
      WeatherAzureAccess.Instance(); 


     //prep dailyinfo arraylist 

      dailyinfo = WeatherDBAccess.Instance().DailyWeatherEvents(dailyinfo); 

И это мой LogCat, «От БД, текущая температура: XX» строки при печати из методов лазури:

01-12 15:15:43.869 29979-30189/pdgt.cat.com.noaahso I/SQLiteAssetHelper: successfully opened database HSO.sqlite 
01-12 15:15:43.869 29979-30189/pdgt.cat.com.noaahso D/WeatherDBAccess: Instance Created /data/data/pdgt.cat.com.noaahso/databases/HSO.sqlite 
01-12 15:15:43.869 29979-30189/pdgt.cat.com.noaahso I/System.out: Current Temp: 54 
01-12 15:15:43.899 29979-30189/pdgt.cat.com.noaahso I/System.out: Weather Event Added 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso D/DB Access: got to dailyweatherevents 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso E/CursorWindow: Failed to read row 1, column -1 from a CursorWindow which has 3 rows, 3 columns. 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err: java.lang.IllegalStateException: Couldn't read row 1, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso D/AzureAccess: WeatherSync thread STARTED! 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at android.database.CursorWindow.nativeGetString(Native Method) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at android.database.CursorWindow.getString(CursorWindow.java:451) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at pdgt.cat.com.noaahso.WeatherDBAccess.GetDailyWeatherEvent(WeatherDBAccess.java:235) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at pdgt.cat.com.noaahso.WeatherDBAccess.DailyWeatherEvents(WeatherDBAccess.java:219) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at pdgt.cat.com.noaahso.WeatherTask.doInBackground(WeatherTask.java:228) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at pdgt.cat.com.noaahso.WeatherTask.doInBackground(WeatherTask.java:47) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at android.os.AsyncTask$2.call(AsyncTask.java:288) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 49 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
01-12 15:15:43.919 29979-30189/pdgt.cat.com.noaahso W/System.err:  at java.lang.Thread.run(Thread.java:818) 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 49 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 49 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 49 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 50 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 50 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 50 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 51 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 51 
01-12 15:15:43.919 29979-29979/pdgt.cat.com.noaahso D/AsyncTask: got to onpostExecute 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 51 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 51 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 51 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 51 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 51 
01-12 15:15:43.919 29979-30298/pdgt.cat.com.noaahso I/System.out: From DB, current temp: 51 

мне нужно сделать использовать FutureCallback для первого курсора, чтобы узнать, когда начинать второй курсор? Или мне нужно сделать мой первый курсор глобальным и дождаться, пока первый запрос будет выполнен, прежде чем я сброшу один курсор для выполнения второго запроса? В поисках решения я узнал, что начало второго курсора дорого. Моя проблема в том, что второй курсор будет использоваться редко (возможно, только onCreate()), и первый курсор будет почти всегда идти, поскольку он постоянно используется для отправки материала в Azure. Также FYI я закрываю свой db onDestroy().

ответ

0

Во-первых, ваша ошибка:

java.lang.IllegalStateException: Не удалось прочитать строку 1, столбец -1 из CursorWindow. Убедитесь, что курсор инициализирован правильно до того, как получает доступ к данным из него.

Это означает, что у вас есть результаты (строка 1), но вы пытаетесь прочитать недопустимый индекс столбца (col -1).

Область проблема, скорее всего, здесь:

wEvent.CurrTemp = dailycursor.getString(dailycursor.getColumnIndex(COLUMN_CURRENT_TEMPERATURES)); 

Вы получаете -1 результат от getColumnIndex, потому что COLUMN_CURRENT_TEMPERATURES не существует в вашем SQL запросе.

Cursor dailycursor = db.rawQuery("SELECT avg(" + COLUMN_CURRENT_TEMPERATURES + "), " + COLUMN_TIME_STAMP + ", " + 
      "CASE WHEN strftime('%M', " + COLUMN_TIME_STAMP + ") < '30' " + 
      "THEN strftime('%H', " + COLUMN_TIME_STAMP + ") " + 
      "ELSE strftime('%H', " + COLUMN_TIME_STAMP + ", '+1 hours') END " + 
      "FROM " + TABLE_WEATHER + " "+ 
      "GROUP BY strftime('%H', " + COLUMN_TIME_STAMP + ", '+30 minutes')", null); 

Вам необходимо включить все столбцы, которые вы намерены читать из вашей ЗЕЬЕСТ:

Cursor dailycursor = db.rawQuery("SELECT avg(" + COLUMN_CURRENT_TEMPERATURES + "), " + COLUMN_CURRENT_TEMPERATURES + ", " + COLUMN_CURRENT_WEATHER_DESCRIPTION + ", " + COLUMN_CURRENT_ICONS + ", " + COLUMN_SEVERE_WEATHER_PRESENT + ", " + COLUMN_TIME_STAMP + ", " + 
      "CASE WHEN strftime('%M', " + COLUMN_TIME_STAMP + ") < '30' " + 
      "THEN strftime('%H', " + COLUMN_TIME_STAMP + ") " + 
      "ELSE strftime('%H', " + COLUMN_TIME_STAMP + ", '+1 hours') END " + 
      "FROM " + TABLE_WEATHER + " "+ 
      "GROUP BY strftime('%H', " + COLUMN_TIME_STAMP + ", '+30 minutes')", null); 
+0

Спасибо за ответ! Так почему мне нужно использовать «SELECT COLUMN_CURRENT_TEMPERATURES» и «SELECT avg (COLUMN_CURRENT_TEMPERATURES)» в android? Я не думаю, что понимаю вашу точку зрения, потому что столбец температуры существует, он находится в запросе, он просто используется в функции avg().Когда я запускаю этот запрос в моем браузере SQL-сервера, он отлично работает. –

+0

Это связано с тем, что, когда вы используете функцию avg(), имя столбца больше не доступно. Вы можете использовать 'avg (column) как columnname', чтобы дать динамическому столбцу имя. – Knossos

+0

Хорошо, что работает! Будет ли более эффективный способ использовать только один курсор вместо двух? Или как у меня это нормально, поскольку второй курсор не будет запрашивать много данных? –