我正在关注这个 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!");
}*/
}
}