运行在同一数据库

时间:2016-01-13 14:59:35

标签: java android multithreading azure android-asynctask

我在asynctask类doInBackground()中初始化数据库实例。数据库实例及其方法在一个单独的类中(我将展示的那个)从asynctask开始,我在Azure客户端的类中启动另一个线程,最终查询数据库类以填充我的azure数据库客户端。回到我的asynctask,然后我再次访问数据库(同时作为第一个查询)来查询数据库以获取单独的信息。似乎有两个游标同时从单独的线程查询导致我出现问题。

下面是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;
}

这些下一个方法来自同一个db类。 &#39; dailycursor&#39;这是造成我麻烦的原因。这些方法在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,&#34;来自DB,当前温度:XX&#34;线条是从azure的方法打印出来的:

    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发送内容。另外,我会关闭我的数据库onDestroy()。

1 个答案:

答案 0 :(得分:0)

首先,您的错误是:

  

java.lang.IllegalStateException:无法读取第1行,col -1   CursorWindow。确保之前正确初始化了Cursor   从中访问数据。

这意味着,您有结果(第1行),但您正在尝试读取无效的列索引(col -1)。

问题领域很可能在这里:

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

您从getColumnIndex获得-1结果,因为您的SQL查询中不存在COLUMN_CURRENT_TEMPERATURES

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

您需要在SELECT语句中包含您想要读取的所有列:

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