声明:学习的书籍《Android应用开发揭秘》,这里记录学习该书籍的日志,引用的相关代码与总结描述,没有商业的用途,完全是自我学习的一个记录,刚刚学习不可避免会出现很多问题,若是有错误还请大家多多批评。
之前已经学习了三种数据操作的方式,还有一种最为常用数据库操作,因为之前的三种数据方式一般只存储一些简单的,数据量较小的数据。如果数据量比较大,需要管理,维护与升级的话,就不能满足需要了。而sqlite数据库则提供这种问题的解决方案。关于为什么使用sqlite数据,网上也有很多关于sqlite数据的优点,简单说一下:
1、 轻量级,它是进程内的数据库引擎,不存在数据库客户端与服务器端。
2、 独立性,sqlite的核心引擎不依赖第三方软件,也不需要安装。
3、 隔离性,sqlite数据库中所有信息都存放在一个文件中,方便管理与维护。
5、 多语言接口,支持很多语言编程接口。
6、 安全性,sqlite数据库通过数据库级上的独占性和共享锁来实现独立事物处理。也就是能够满足同事多个线程同个时间从数据库中读取数据,但是只有一个是可写的。
数据库操作,无非就是针对数据的增删改查,以及表的创建于删除,下面例子中包含了以上操作。该实例默认会创建一data1数据库并且创建表table1,然后设定按键的监听,点击方向键左时会添加一条数据,方向键右会删除一条数据,数字键1为修改最后一条数据,数字键2为删除表,数字键3为删除数据库。
关键源码:
public class DatabaseDataActivity extends Activity { private static int count = 0; private sqliteDatabase sqliteDatabase = null; //数据库对象 private final static String DATABASE_NAME = "data1";//数据库名 private final static String TABLE_NAME = "table1"; //表名 private final static String TABLE_ID = "_id"; private final static String TABLE_NUM = "num"; private final static String TABLE_DATA = "data"; private final static String CREATE_TABLE = "Create table " + TABLE_NAME + " (" + TABLE_ID + " integer primary key," + TABLE_NUM + " integer," + TABLE_DATA + " Text)"; LinearLayout linearLayout = null; ListView listView = null; //用来显示数据库中得数据 /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); linearLayout = new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setBackgroundColor(android.graphics.Color.BLACK); listView = new ListView(this); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT); listView.setBackgroundColor(Color.BLACK); linearLayout.addView(listView,params); setContentView(linearLayout); //设置显示linearLayout布局 sqliteDatabase = this.openOrCreateDatabase(DATABASE_NAME,MODE_PRIVATE,null); //打开或者创建数据库 try { sqliteDatabase.execsql(CREATE_TABLE); } catch (Exception e) { UpdataAdapter(); } } //更新并显示视图 private void UpdataAdapter() { // 获取数据库Phones的Cursor Cursor cur = sqliteDatabase.query(TABLE_NAME,new String[] { TABLE_ID,TABLE_NUM,TABLE_DATA },null,null); count = cur.getCount(); if (cur != null && cur.getCount() >= 0){ // ListAdapter是ListView和后台数据的桥梁 ListAdapter adapter = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_2,// 定义List中每一行的显示模板,表示每一行包含两个数据项 cur,// 数据库的Cursor对象 new String[] { TABLE_NUM,// 从数据库的TABLE_NUM和TABLE_DATA两列中取数据 new int[] { android.R.id.text1,android.R.id.text2 });// 与NAME和NUMBER对应的Views listView.setAdapter(adapter);/* 将adapter添加到m_ListView中 */ } } public boolean onKeyDown(int keyCode,KeyEvent event) { // TODO Auto-generated method stub if (keyCode == KeyEvent.KEYCODE_BACK){ sqliteDatabase.close(); this.finish(); return true; } return super.onKeyDown(keyCode,event); } public boolean onKeyUp(int keyCode,KeyEvent event) { switch (keyCode){ case KeyEvent.KEYCODE_DPAD_LEFT: AddData(); break; case KeyEvent.KEYCODE_DPAD_RIGHT: DeleteData(); break; case KeyEvent.KEYCODE_1: UpData(); break; case KeyEvent.KEYCODE_2: DeleteTable(); break; case KeyEvent.KEYCODE_3: DeleteDataBase(); break; } return true; } //删除数据库 private void DeleteDataBase() { this.deleteDatabase(DATABASE_NAME); this.finish(); } //删除表 private void DeleteTable() { sqliteDatabase.execsql("DROP TABLE " + TABLE_NAME); this.finish(); } //更新数据 private void UpData() { ContentValues values = new ContentValues(); values.put(TABLE_NUM,count); values.put(TABLE_DATA,"修改后的数据"+count); //更新数据 sqliteDatabase.update(TABLE_NAME,values,TABLE_NUM + "=" +Integer.toString(count-1),null); UpdataAdapter(); } //删除数据 private void DeleteData() { // TODO Auto-generated method stub sqliteDatabase.execsql("delete from " + TABLE_NAME + " where _id = " + Integer.toString(count)); count--; if(count < 0){ count = 0; } UpdataAdapter(); } //添加数据 private void AddData() { // TODO Auto-generated method stub ContentValues cv = new ContentValues(); cv.put(TABLE_NUM,count); cv.put(TABLE_DATA,"测试数据库数据" + count); /* 插入数据 */ sqliteDatabase.insert(TABLE_NAME,cv); count++; UpdataAdapter(); } }
一般查看数据库可以先把该对应目录下得数据库文件导出后,使用sqliteSpy.exe工具来查看,数据库文件的存放地址与之前的数据操作的存储目录一致,数据库文件放在databases文件下。该工具可以到我的资源里去下载。
@H_301_41@
【遇到问题】
开始在创建表的时候,我设置的主键为ID,但是实际在运行示例的时候,总是报_ID找不到,比较纳闷,我没有建立这一列啊。后来发现,针对sqlite的表创建时必须_ID,因为底层类在找得时候,就是以_ID来找,改过来之后就可以运行了。
【扩展学习】游标Cursor的使用
关于 Cursor,在你理解和使用 Android Cursor 的时候你必须先知道关于 Cursor 的几件事情:
Cursor 是每行的集合。@H_301_41@使用 moveToFirst() 定位第一行。@H_301_41@你必须知道每一列的名称。@H_301_41@你必须知道每一列的数据类型。@H_301_41@Cursor 是一个随机的数据源。@H_301_41@所有的数据都是通过下标取得。@H_301_41@关于 Cursor 的重要方法:
close() —— 关闭游标,释放资源@H_301_41@copyStringToBuffer(int columnIndex,CharArrayBuffer buffer) —— 在缓冲区中检索请求的列的文本,将将其存储@H_301_41@getColumnCount() —— 返回所有列的总数@H_301_41@getColumnIndex(String columnName) —— 返回指定列的名称,如果不存在返回-1@H_301_41@getColumnIndexOrThrow(String columnName) —— 从零开始返回指定列名称,如果不存在将抛出IllegalArgumentException 异常。@H_301_41@getColumnName(int columnIndex) —— 从给定的索引返回列名@H_301_41@getColumnNames() —— 返回一个字符串数组的列名@H_301_41@getCount() —— 返回Cursor 中的行数@H_301_41@moveToFirst() —— 移动光标到第一行@H_301_41@moveToLast() —— 移动光标到最后一行@H_301_41@moveToNext() —— 移动光标到下一行@H_301_41@moveToPosition(int position) —— 移动光标到一个绝对的位置@H_301_41@moveToPrevIoUs() —— 移动光标到上一行
if (cur.moveToFirst() == false){@H_301_41@//为空的Cursor@H_301_41@return;@H_301_41@}
访问 Cursor 的下标获得其中的数据
int nameColumnIndex = cur.getColumnIndex(People.NAME);@H_301_41@String name = cur.getString(nameColumnIndex);@H_301_41@现在让我们看看如何循环 Cursor 取出我们需要的数据
while(cur.moveToNext()){@H_301_41@//光标移动成功@H_301_41@//把数据取出@H_301_41@}
当cur.moveToNext() 为假时将跳出循环,即 Cursor 数据循环完毕。