【问题标题】:Why can't I add these default values in my SQLite database in Android?为什么我不能在 Android 的 SQLite 数据库中添加这些默认值?
【发布时间】:2013-04-16 21:28:27
【问题描述】:

所以我正在构建一个警报应用程序。我想在首次安装应用程序时显示一些默认警报。例如,上午 7 点、上午 8 点和上午 9 点的 3 个警报。下面是我的代码。

调用getAllAlarms() 来检索要显示的警报列表。在第一次加载时,数据库将为空,所以如果是这种情况,我想插入一些默认值。这可以在else 语句中看到,我在其中添加警报,然后对其自身进行递归调用。我的理解是在添加了3个警报之后,我再次调用getAllAlarms,它应该可以正常进入if语句。在调试System.out.println 语句中可以看到这种情况。警报列表按预期打印出来,但是在某处显示该方法再次被调用,这导致列表变为空,如上一个调试语句所示。

你能看出问题出在哪里吗?我已经在项目中进行了文件搜索,除了方法本身和ListActivity 之外,我没有在任何地方调用删除方法,也没有调用getAllAlarms。我认为问题必须定位在getAllAlarms 方法中,但我找不到。是递归调用吗?

   // Getting All Alarms
public List<Alarm> getAllAlarms() {
    List<Alarm> alarmList = new ArrayList<Alarm>();
    // Select All Query
    String selectQuery = "SELECT  * FROM " + TABLE_ALARMS;

    SQLiteDatabase db = this.getWritableDatabase();
    Cursor cursor = db.rawQuery(selectQuery, null);

    // looping through all rows and adding to list
    if (cursor.moveToFirst()) {
        do {
            Alarm alarm = new Alarm();
            alarm.setID(cursor.getInt(0));
            alarm.setHour(cursor.getInt(1));
            alarm.setMinutes(cursor.getInt(2));
            // Adding alarm to list
            alarmList.add(alarm);
            System.out.println("inside loop");
            System.out.println(alarmList);

        } while (cursor.moveToNext());
    }
    else
    {           
        System.out.println("Adding default values...");
        addAlarm(new Alarm(7,0));
        addAlarm(new Alarm(8,0));
        addAlarm(new Alarm(9,0));
        System.out.println("Finished adding default values...");
        getAllAlarms();
    }

    System.out.println("before");
    System.out.println(alarmList);
    System.out.println("after");
    // return alarm list
    return alarmList;
}

这是我的添加方法:

void addAlarm(Alarm alarm) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(KEY_HOUR, alarm.getHour()); // Alarm Name
    values.put(KEY_MINUTES, alarm.getMinutes()); // Alarm Phone

    // Inserting Row
    db.insert(TABLE_ALARMS, null, values);
    db.close(); // Closing database connection
}

调试输出:

04-23 16:17:49.261: I/System.out(10938): Adding default values...
04-23 16:17:49.291: I/System.out(10938): Finished adding default values...
04-23 16:17:49.291: I/System.out(10938): inside loop
04-23 16:17:49.291: I/System.out(10938): [07:00]
04-23 16:17:49.296: I/System.out(10938): inside loop
04-23 16:17:49.296: I/System.out(10938): [07:00, 08:00]
04-23 16:17:49.296: I/System.out(10938): inside loop
04-23 16:17:49.296: I/System.out(10938): [07:00, 08:00, 09:00]
04-23 16:17:49.296: I/System.out(10938): before
04-23 16:17:49.296: I/System.out(10938): [07:00, 08:00, 09:00]
04-23 16:17:49.296: I/System.out(10938): after
04-23 16:17:49.296: I/System.out(10938): before
04-23 16:17:49.296: I/System.out(10938): []
04-23 16:17:49.296: I/System.out(10938): after

更新::

我试过没有用:

if (cursor.moveToFirst()) { 做 { 警报警报 = 新警报(); alarm.setID(cursor.getInt(0)); alarm.setHour(cursor.getInt(1)); alarm.setMinutes(cursor.getInt(2)); // 添加警报到列表 警报列表.add(警报); System.out.println("内部循环"); System.out.println(alarmList);

    } while (cursor.moveToNext());            
}
else
{           
    System.out.println("Adding default values...");
    addAlarm(new Alarm(7,0));
    addAlarm(new Alarm(8,0));
    addAlarm(new Alarm(9,0));
    System.out.println("Finished adding default values...");
}

if(alarmList.isEmpty() || alarmList == null)
{
    System.out.println("test"  + alarmList);
    getAllAlarms();
}

但是,如果我删除 if 语句以检查空列表,然后我将检查添加到数据库外部和 ListActivity 内部,这将自行工作。这不是我想要的。我不想在 Database 类之外处理默认值插入。

否则 {
System.out.println("正在添加默认值..."); addAlarm(新警报(7,0)); addAlarm(新警报(8,0)); addAlarm(新警报(9,0)); System.out.println("完成添加默认值..."); }

ListActivity内部:

protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm_list);

Database db = new Database(AlarmListActivity.this);
list = db.getAllAlarms();
if(list.isEmpty())
{
    list = db.getAllAlarms();
}
....
....

}

【问题讨论】:

    标签: java android debugging android-sqlite default-value


    【解决方案1】:

    正如@umesh 建议的那样,使用getReadableDatabase(),不需要db.close(),但最重要的是把你写的东西包装在一个事务中:

    db.beginTransaction();
    // insert
    db.setTransactionSuccessful();
    db.endTransaction();
    

    更新:单例(ish)模式

    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    
    public class DBOpenHelper extends SQLiteOpenHelper {
    
        private enum OpenHelperEnum {
            INSTANCE; // Singleton instance;
    
            // Instance of dbHelper for all DB access in threads
            private SQLiteOpenHelper dbHelper = null;
            private SQLiteDatabase database = null;
    
            public SQLiteDatabase getDB(final Context context) {
                if (dbHelper == null) {
                    dbHelper = new DBOpenHelper(context);
                }
                if (database == null) {
                    database = dbHelper.getReadableDatabase();
                }
                return database;
            }
        }
    
        public DBOpenHelper(final Context context) {
            super(context, "DBName", null, 1);
        }
    
        @Override
        public void onCreate(final SQLiteDatabase database) {
            // ...
        }
    
        @Override
        public void onUpgrade(final SQLiteDatabase database, final int oldVersion, final int newVersion) {
            // ...
        }
    
        @Override
        public void onDowngrade(final SQLiteDatabase database, final int oldVersion, final int newVersion) {
            // ...
        }
    
        public static SQLiteDatabase getDB(final Context context) {
            return DBOpenHelper.OpenHelperEnum.INSTANCE.getDB(context);
        }
    }
    

    获取数据库使用:

    final SQLiteDatabase db = DBOpenHelper.getDB(this);
    

    【讨论】:

    • 删除了 db.close() 然后用你建议的但结果相同的插入包围。
    【解决方案2】:

    getAllAlarms方法里改一下

    getWritableDatabase
    

    getReadableDatabase  
    

    如下图

    String selectQuery = "SELECT  * FROM " + TABLE_ALARMS;
    
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.rawQuery(selectQuery, null);
    

    【讨论】:

    • 尝试去掉addAlarm()中的db.close(),如果不行,再看
    • 已删除,但仍然无法正常工作。 getAllAlarms 方法以某种方式被调用了 3 次...
    猜你喜欢
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 2016-03-10
    • 2022-01-12
    • 1970-01-01
    相关资源
    最近更新 更多