0

我正在关注这个 AlarmClock 教程(项目 .zip 也可在 GitHub 上获得),了解如何为 Android 构建我的闹钟。我修复了一些不好的代码等,但它仍然无法正常工作。

我遇到了很多 SQLiteDatabase 泄漏并修复了它们(我认为),但根据我的观察,每次删除警报或重新启动应用程序时数据仍然会错误地更新。

还有一些其他小错误,例如根本没有将新警报添加到数据库中的错误,但这是另一个问题。

所以,我相信问题出在某个地方:

package com.example.vedran.valarm;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;

import com.example.vedran.valarm.AlarmContract.Alarm;

import java.util.ArrayList;
import java.util.List;

public class AlarmDBHelper extends SQLiteOpenHelper {
    public static final int DATABASE_VERSION=1;
    public static final String DATABASE_NAME = "alarmclock.db";
    private static AlarmDBHelper database;

private static final String SQL_CREATE_ALARM =
        "CREATE TABLE " + Alarm.TABLE_NAME + " (" +
        Alarm._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
        Alarm.COLUMN_NAME_ALARM_NAME + " TEXT," +
        Alarm.COLUMN_NAME_ALARM_TIME_HOUR + " INTEGER," +
        Alarm.COLUMN_NAME_ALARM_TIME_MINUTE + " INTEGER," +
        Alarm.COLUMN_NAME_ALARM_REPEAT_DAYS + " TEXT," +
        Alarm.COLUMN_NAME_ALARM_REPEAT_WEEKLY + " BOOLEAN," +
        Alarm.COLUMN_NAME_ALARM_TONE + " TEXT," +
        Alarm.COLUMN_NAME_ALARM_ENABLED + " BOOLEAN" + " )";
private static final String SQL_DELETE_ALARM =
        "DROP TABLE IF EXISTS" + Alarm.TABLE_NAME;

public AlarmDBHelper(Context context){
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(SQL_CREATE_ALARM);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL(SQL_DELETE_ALARM);
    onCreate(db);
}
public static synchronized AlarmDBHelper getInstance(Context context){
    if(database == null){
        database = new AlarmDBHelper(context.getApplicationContext());
    }
    return database;
}

/**
 * objasnim kasnije
 * @param c
 * @return
 */
private AlarmModel populateModel(Cursor c){
    AlarmModel model = new AlarmModel();
    model.id = c.getLong(c.getColumnIndex(Alarm._ID));
    model.name = c.getString(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_NAME));
    model.timeHour = c.getInt(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_TIME_HOUR));
    model.timeMinute = c.getInt(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_TIME_MINUTE));
    model.repeatWeekly = c.getInt(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_REPEAT_WEEKLY)) != 0;
    model.alarmTone = c.getString(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_TONE)) != "" ? Uri.parse(c.getString(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_TONE))) : null;
    model.isEnabled = c.getInt(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_ENABLED)) != 0;

    String[] repeatingDays = c.getString(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_REPEAT_DAYS)).split(",");
    for(int i=0;i<repeatingDays.length;i++){
        model.setRepeatingDay(i, !repeatingDays[i].equals("false"));
    }
    return model;
}
private ContentValues populateContent(AlarmModel model){
    ContentValues values = new ContentValues();
    values.put(Alarm.COLUMN_NAME_ALARM_NAME, model.name);
    values.put(Alarm.COLUMN_NAME_ALARM_TIME_HOUR, model.timeHour);
    values.put(Alarm.COLUMN_NAME_ALARM_TIME_MINUTE, model.timeMinute);
    values.put(Alarm.COLUMN_NAME_ALARM_REPEAT_WEEKLY, model.repeatWeekly);
    values.put(Alarm.COLUMN_NAME_ALARM_TONE, model.alarmTone != null ? model.alarmTone.toString() : "");
    values.put(Alarm.COLUMN_NAME_ALARM_ENABLED, model.isEnabled);

    StringBuilder buildRepeatingDays = new StringBuilder();
    for(int i=0; i<7; i++){
        buildRepeatingDays.append(model.getRepeatingDay(i));
        buildRepeatingDays.append(",");
    }
    String repeatingDays = buildRepeatingDays.toString();
    values.put(Alarm.COLUMN_NAME_ALARM_REPEAT_DAYS, repeatingDays);
    return values;
    }
public long createAlarm(AlarmModel model){
    ContentValues values = populateContent(model);
    SQLiteDatabase db = this.getWritableDatabase();
    long stat = db.insert(Alarm.TABLE_NAME, null, values);
    db.close();
    return stat;
}
public long updateAlarm(AlarmModel model){
    ContentValues values = populateContent(model);
    SQLiteDatabase db = this.getWritableDatabase();
    long stat = db.update(Alarm.TABLE_NAME, values, Alarm._ID + " = " + String.valueOf(model.id), null);
    db.close();
    return stat;
}
public AlarmModel getAlarm(long id){
    SQLiteDatabase db = this.getReadableDatabase();
    String select = "SELECT * FROM " + Alarm.TABLE_NAME + " WHERE " + Alarm._ID + " = " + String.valueOf(id);
    Cursor c = db.rawQuery(select, null);
    if(c.moveToNext()){
        AlarmModel model = populateModel(c);
        c.close();
        db.close();
        return model;
    }
    c.close();
    db.close();
    return null;
}

public List<AlarmModel> getAlarms(){
    SQLiteDatabase db = this.getReadableDatabase();
    String select = "SELECT * FROM " + Alarm.TABLE_NAME;
    Cursor c = db.rawQuery(select, null);

    List<AlarmModel> alarmList = new ArrayList<>();
    while(c.moveToNext()){
        alarmList.add(populateModel(c));
    }
    c.close();
    db.close();
    if(!alarmList.isEmpty()){
        return alarmList;
    }
    return null;
}
public int deleteAlarm(long id) {
    SQLiteDatabase db = this.getWritableDatabase();
    /*int br = db.delete(Alarm.TABLE_NAME, Alarm._ID + " = ?",
            new String[]{String.valueOf(id)});*/
    int br = db.delete(Alarm.TABLE_NAME, Alarm._ID + " = " + String.valueOf(id), null);
    db.close();
    return br;
}
}

这里有一些处理我的数据库的方法(整个类和活动太大,无法在此处添加它们,但它们可以在 GitHub 上找到):

在 AlarmListActivity 里面

public void setAlarmEnabled(long id, boolean isEnabled){
    AlarmManagerHelper.cancelAlarms(this);
    AlarmModel model = dbHelper.getAlarm(id);
    if(model!=null) {
        model.isEnabled = isEnabled;
        dbHelper.updateAlarm(model);
    }
    //mAdapter.setAlarms(dbHelper.getAlarms());
    //mAdapter.notifyDataSetChanged();

    AlarmManagerHelper.setAlarms(this);
}
public void deleteAlarm(long id) {
    final long alarmId = id;
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Please confirm deletion")
            .setTitle("Delete alarm?")
            .setCancelable(true)
            .setNegativeButton("Cancel", null)
            .setPositiveButton("Ok", new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    //Cancel Alarms
                    AlarmManagerHelper.cancelAlarms(mContext);
                    //Delete alarm from DB by id
                    dbHelper.deleteAlarm(alarmId);
                    //Refresh the list of the alarms in the adaptor
                    mAdapter.setAlarms(dbHelper.getAlarms());
                    //Notify the adapter the data has changed
                    mAdapter.notifyDataSetChanged();
                    //Set the alarms
                    AlarmManagerHelper.setAlarms(mContext);
                }
            }).show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(resultCode == RESULT_OK){


        mAdapter.setAlarms(dbHelper.getAlarms());
        mAdapter.notifyDataSetChanged();
        /*if(dbHelper.getAlarms() == null){
            throw new NullPointerException("told ya db was empty!");
        }*/
    }
}
4

0 回答 0