探索Android应用开发(五)
学习目标:
- 完善数据库操作部分
学习目的:
- 掌握Android的数据库
学习收获:
所有的Android数据库都被存储在/data/data/<package_name>/databases路径下。默认情况下,所有的数据库都是私有的,只能被创建它的应用访问。要想在各个应用之间分享数据库,可以使用Content Provider。数据库设计是个很广泛的话题,但是在Android里,最佳实践仍旧是要高度关注的。特别是,当在资源受限的设备上创建数据库时,利用范式来减少数据冗余是很重要的。
ContentValues对象被用来向数据库表中插入新的行,每一个Content Values对象都表示一行。Android提供了在Acitivty中管理Cursor的机制,startManagingCursor方法把Cursor的生命期和父Activity生命期绑定在一起。当使用完Cursor后,只需要调用stopManagingCursor方法。
在设计数据库时,有这么两点应该特别注意:
- 文件(例如图片或音频)通常是不存放在数据库表中。实际上,使用字符串存储这个文件的路径,特别是URI。
- 如果没有严格的要求,强烈推荐所有的表应该包含一个自增长的字段,来惟一标示一行。如果你要使用Content Provider,那么唯一ID是强制的。
Adapter是一个架在数据和用户界面View之间的桥梁。ArrayAdapter和SimpleCursorAdapter是比较有用的adpter。
Android采用Sqlite作为数据库,但是这个数据库支持的类型有限,根据它的文档,可以知道其只支持INTEGER, REAL, TEXT, BLOB或者是NULL,注意了,没有时间/日期类型。
经过一番查阅,我们有两种方法可以解决,第一种就是把时间格式化成字符串,采用TEXT存储;第二种就是把时间转化成毫秒,采用INTEGER存储。这里倾向于采用第二种方式,因为第一种方式容易因为忘记了时间格式,造成读取的时候出错,采用第二种方式以后,不用担心这个问题。
解决了这个问题以后,另一个问题就会出现了。因为我们在数据库中存储的是INTEGER类型,造成了SimpleCursorAdapter读到 INTEGER,直接显示在视图上,这是一个非常不友好的问题。很无奈,视图层和数据层直接绑定,出现这个问题是一定的。幸好Android已经想到了这一点,它在SimpleCursorAdapter中提供了ViewBinder来处理这个问题。我们可以使用这个类,从Cursor中获取到数据以后,经过加工,然后再设定View的值。如下所示:
public class PurseViewBinder implements ViewBinder{ public boolean setViewValue(View view, Cursor cursor, int columnIndex) { int conTimeIndex = cursor.getColumnIndexOrThrow(PurseDbAdapter.KEY_TIME); if (columnIndex == conTimeIndex) { long consumeTimeLong = cursor.getLong(conTimeIndex); Date date = new Date(consumeTimeLong); DateFormat formater = new SimpleDateFormat("yyyy-MM-dd hh:mm"); String consumeStr = formater.format(date); TextView timeView = (TextView) view; timeView.setText(consumeStr); return true; } else{ return false; } } } |
有了这个以后,我们就可以在SimpleCursorAdapter使用了,如下所示:
private void fillData() { // Get all of the notes from database and create the item list cursor = adapter.fetchAll(); this.startManagingCursor(cursor); // An array of column names that will be added to the Map associated with each item. String[] from = new String[]{PurseDbAdapter.KEY_ROWID,PurseDbAdapter.KEY_TYPE, PurseDbAdapter.KEY_MONEY, PurseDbAdapter.KEY_TIME}; //The views that should display column in the "from" parameter. These should all be TextViews. int[] to = {R.id._id, R.id.type, R.id.money, R.id.consumeTime}; // Now create an array adapter SimpleCursorAdapter listAdapter = new SimpleCursorAdapter(this, R.layout.notes_row, cursor, from, to); ViewBinder binder = new PurseViewBinder(); listAdapter.setViewBinder(binder); this.setListAdapter(listAdapter); } |