我在asynctask類doInBackground()中初始化數據庫實例。數據庫實例及其方法位於一個單獨的類中(我將展示的那個類)從asynctask中,我爲Azure客戶端啓動另一個類的線程,最終查詢數據庫類來填充我的azure數據庫客戶端。回到我的asyncTask,我再次訪問數據庫(同時作爲第一個查詢)來查詢數據庫以獲取單獨的信息。似乎有兩個遊標同時從單獨的線程查詢正在導致我的問題。在同一數據庫上運行的不同線程中的多個遊標
下面是使用第一個遊標向Azure發送內容的db類中的方法。這些方法是從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;
}
這些下一個方法來自同一個db類。這裏的'每日一趟'是造成我麻煩的原因。這些方法在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是數據庫類。該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,「從DB,當前溫度: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我關閉我的數據庫onDestroy()。
感謝您的答覆!那麼爲什麼我需要在android中使用'SELECT COLUMN_CURRENT_TEMPERATURES'和'SELECT avg(COLUMN_CURRENT_TEMPERATURES)'?我不認爲我理解你的觀點,因爲溫度列存在,它在查詢中,它只是在avg()函數中使用。當我在我的sqlite數據庫瀏覽器中運行這個查詢時,它完美地工作。 –
這是因爲當您使用avg()函數時,列的名稱不再可用。您可以使用'avg(列)作爲列名'給動態列一個名稱。 – Knossos
好的,工作!會有更有效的方法來使用一個光標而不是兩個?或者我有多好,因爲第二個遊標不會查詢大量數據? –