转载请注明出处,谢谢!
自己做的手机小应用以前用的是SharedPreferences存储的数据。现在需要换成用sqlite数据库存储,那就要重构代码了。
以下探讨部分代码的重构:
以前的代码:
List<Task> data;
SharedPreferences spf;
Editor editor;
editor = spf.edit();
data = getData();
public List<Task> getData() {
List<Task> data = new ArrayList<Task>();
int size = spf.getInt("count", 0);
for (int i = 0; i < size; i++) {
data.add(new Task(spf.getString("Task" + i + "Title", ""), spf
.getString("Task" + i + "Action", ""), spf.getBoolean(
"Task" + i + "isCompleted", false)));
}
return data;
}
保存数据的方法:每次添加新任务、删除任务、修改任务等操作都需要保存数据。每次保存数据之前,先把原有SharedPreferences文件清空,再从一个存放所有任务信息的List中依次写进去。
private void saveSpf() {
editor.clear();//清空SharedPreferences文件
for (int i = 0; i < data.size(); i++) {
Task task = data.get(i);
editor.putString("Task" + i + "Title", task.getTitle());
editor.putString("Task" + i + "Action", task.getAction());
editor.putBoolean("Task" + i + "isCompleted", task.isCompleted());
}
editor.putInt("count", data.size());
editor.commit();
}
添加新任务
private void addTask(Intent intent) {
String titleStr = intent.getStringExtra("titleStr");
String actionStr = intent.getStringExtra("actionStr");
int position = intent.getIntExtra("position", 0);
data.add(position, new Task(titleStr, actionStr));
saveSpf();
}
private void delTask(int position) {
data.remove(position);
saveSpf();
MyAdapter<String> adapter = new MyAdapter<String>(this,
android.R.layout.simple_list_item_1, data);
setListAdapter(adapter);
}
private void amendTask(Intent intent) {
String titleStr = intent.getStringExtra("titleStr");
String actionStr = intent.getStringExtra("actionStr");
int position = intent.getIntExtra("position", 0);
data.set(position, new Task(titleStr, actionStr));
saveSpf();
}
为什么每次操作,都需要先清空原本地文件呢?这是因为每个任务在列表显示时都有个“位置”。假设这个“位置”是每个任务的固有属性,那么进行添加和删除某个任务时,这个任务以下的所有任务的位置都要改变。这就像线性表中添加、删除一个元素一样麻烦。以前的代码中偷懒地使用了List的有序性,每次操作都是对List中的元素操作,然后再依次写到本地文件中。
那么转换成用数据库存储,应该如何操作呢?每次添加、删除操作都清空数据库表中的信息,再重新往表中写数据?很明显,这样效率很低。于是,我想到在数据库表中增加一个字段,记录一个任务之前那个任务的编号(在数据库表中的行号,第一个任务的该字段设为-1)——类似链表的方式。这样以来,从数据库读取数据显示列表、添加任务、删除任务、修改任务就要按以下操作进行(本人还没有在android中操作数据库的经验,以下只是个想法,还没实现):
例如数据库表中这样存放了一些元素:
任务编号 | 任务名 | 上一个任务编号 |
---|---|---|
1 | firstTask | 0 |
2 | thirdTask | 3 |
3 | secondTask | 1 |
读取数据以显示列表
1.定义变量i=0
2.查询“上一个任务编号”=i那一行,得到位置是“第一个”的任务,变量i=这个任务的“任务编号”*
3.重复第二步,到返回结果为空为止
添加任务
在“第一个”位置添加任务
任务编号 | 任务名 | 上一个任务编号 |
1 | firstTask | 4 |
2 | thirdTask | 3 |
3 | secondTask | 1 |
4 | one | 0 |
1.添加到数据库
2.根据任务名,查询该任务的编号,存放到变量i中
3.更新“上一个任务编号”为0的记录,使它的“上一个任务编号”字段更新为i
4.更新“任务编号”为i的记录,使它的“上一个编号”为0
在“firstTask”任务后面添加任务
任务编号 | 任务名 | 上一个任务编号 |
1 | firstTask | 0 |
2 | thirdTask | 3 |
3 | secondTask | 4 |
4 | two | 1 |
1.添加到数据库
2.根据任务名,查询该任务的编号,存放到变量i中
3.更新“上一个任务编号”为1的记录,使它的“上一个任务编号”字段更新为i
4.更新“任务编号”为i的记录,使它的“上一个编号”为1
在“最后一个”位置添加任务
任务编号 | 任务名 | 上一个任务编号 |
1 | firstTask | 0 |
2 | thirdTask | 3 |
3 | secondTask | 1 |
4 | four | 2 |
1.添加到数据库
2.根据任务名,查询该任务的编号,存放到变量i中
3.更新“上一个任务编号”为2的记录,使它的“上一个任务编号”字段更新为i
4.更新“任务编号”为i的记录,使它的“上一个编号”为2
1.添加到数据库
2.根据任务名,查询该任务的编号,存放到变量i中
3.从应用中获取添加任务已存在“某个任务”之后,查询这个已存在任务的编号(添加位置“第一个”,得到的0),存到变量pre中(例如添加任务位置是“firstTask”之后,则查询"firstTask"的编号,存到变量pre中)
4.如果查询到“上一个任务编号”为pre的记录,则使它的“上一个任务编号”字段更新为i
5.更新“任务编号”为i的记录,使它的“上一个编号”为pre
删除任务
1.根据任务名,在表查询该任务的编号,存到变量i中,查询“上一个任务编号”,存到变量pre中
2.如果查询到“上一个任务编号”为i的记录,则使它的“上一个任务编号”字段更新为pre
3.根据任务名,删除记录
1.找到任务原编号
2.根据编号,使用updata语句更新
更新代码
private static final String TABLE_NAME = "Table_Task";
private static final String[] TABLE_TODOTASK_COLUMS = { "taskID", "title", "preTaskId" };
MyDBHelper dbHelper;
SQLiteDatabase db;
dbHelper = new MyDBHelper(this, "Tasklist.db3", null, 1);
db = dbHelper.getReadableDatabase();
从数据库读取数据
public List<Task> getData() {
List<Task> data = new ArrayList<Task>();
int i = 0;
Cursor cs;
do {
cs = db.query(TABLE_NAME, TABLE_TODOTASK_COLUMS, "preTaskId=?",
new String[] { "" + i }, null, null, null);
if (cs.moveToFirst()) {
String title = cs.getString(1);
Task task = new Task(title);
data.add(task);
i = cs.getInt(0);
} else
break;
} while (cs.moveToFirst());
return data;
}
添加数据
private void addTask(Intent intent) {
String titleStr = intent.getStringExtra("titleStr");//从另外的activity得到数据
int position = intent.getIntExtra("position", 0);
ContentValues addvalues = new ContentValues();
addvalues.put(TABLE_TODOTASK_COLUMS[1], titleStr);
int exTaskPre=0;
int newTaskId=0;
int exLastTaskId=0;
if (position == data.size()) {//插入的元素是最后一个
Task ex_lastTask=data.get(position-1);//得到插入前最后一个元素
Cursor cs = db.query(TABLE_NAME,
new String[] { TABLE_TODOTASK_COLUMS[0] }, "title=?",
new String[] { ex_lastTask.getTitle() }, null, null, null);
if (cs.moveToFirst()) {
exLastTaskId = cs.getInt(0);//得到得到插入前最后一个元素的id
}
addvalues.put(TABLE_TODOTASK_COLUMS[2], exLastTaskId);//设定插入的新元素的preTaskId字段为插入前最后一个元素的id
db.insert(TABLE_NAME, null, addvalues);//插入新任务
} else {
Task ex_Task = data.get(position);// 得到这个位置的元素
//在数据库中查询这个元素的“preTaskID”属性
Cursor cs = db.query(TABLE_NAME,
new String[] { TABLE_TODOTASK_COLUMS[2] }, "title=?",
new String[] { ex_Task.getTitle() }, null, null, null);
if (cs.moveToFirst()) {
exTaskPre = cs.getInt(0);
}
addvalues.put(TABLE_TODOTASK_COLUMS[6],exTaskPre);//将新插入元素的preTaskID属性设置为ex_Task_pre
db.insert(TABLE_NAME, null, addvalues);//插入新任务
//获取刚插入新任务的ID
cs = db.query(TABLE_NAME,
new String[] { TABLE_TODOTASK_COLUMS[0] }, "title=?",
new String[] { titleStr }, null, null, null);
if (cs.moveToFirst()) {
newTaskId = cs.getInt(0);
}
ContentValues updValues = new ContentValues();
updValues.put(TABLE_TODOTASK_COLUMS[2], newTaskId);//更新插入前在这个位置的元素的preTaskId字段
db.update(TABLE_NAME,updValues,"title=?",newString[]{ex_Task.getTitle()});
}
data.add(position, new Task(titleStr));
}
删除数据
private void delTask(int position) {
Task delTask = data.get(position);
int delTaskPre=0;
if(position!=data.size()-1){
Cursor cs = db.query(TABLE_NAME,
new String[] { TABLE_TODOTASK_COLUMS[2] }, "title=?",
new String[] { delTask.getTitle() }, null, null, null);
if (cs.moveToFirst()) {
delTaskPre = cs.getInt(0);
}
Task nextTask=data.get(position+1);
ContentValues updValues = new ContentValues();
updValues.put(TABLE_TODOTASK_COLUMS[2], delTaskPre);
db.update(TABLE_NAME, updValues, "title=?", new String[] { nextTask.getTitle() });
}
db.delete(TABLE_NAME, "title=?", new String[] { delTask.getTitle() });
data.remove(position);
MyAdapter<String> adapter = new MyAdapter<String>(this,
android.R.layout.simple_list_item_1, data);
setListAdapter(adapter);
}
修改数据
private void amendTask(Intent intent) {
String titleStr = intent.getStringExtra("titleStr");
int position = intent.getIntExtra("position", 0);
//先根据修改任务的位置获取原任务
Task amTask = data.get(position);
int amTaskId=0;
Cursor cs = db.query(TABLE_NAME, new String[]{TABLE_TODOTASK_COLUMS[0]}, "title=?", new String[]{amTask.getTitle()}, null, null, null);
if(cs.moveToFirst()){
amTaskId=cs.getInt(0);//以原任务title获取任务的编号
}
ContentValues updValues = new ContentValues();
updValues.put(TABLE_TODOTASK_COLUMS[1], titleStr);
db.update(TABLE_NAME, updValues, "taskId=?", new String[] { ""+amTaskId });//以任务的编号更新数据
data.set(position, new Task(titleStr, actionStr));
}
参考开发文档:http://developer.android.com/reference/android/database/package-summary.html
http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html