Android游戏开发之数据库SQLite 详细介绍(十七)

239
回复
1079311
查看
  [复制链接]

249

主题

278

帖子

17

安币

初级码农

Rank: 1

发表于 2011-9-3 00:20:44 | 显示全部楼层 |阅读模式
带你走进游戏开发的世界之数据库SQLite 详细介绍

数据库SQLite介绍
   
        数据库最经典的四个操作 添加、删除、修改、查找,在处理大量数据的时候使用数据库可以帮我们迅速定位当前须要处理的数据,举个例子 好比现在要实现一个搜索功能 用数据库的话只须要其中一个搜索条件 一个数据库语句就可以迅速的在N条数据中找到我们需要的数据,如果不使用数据库那么查找起来会非常麻烦,效率大打折扣,所以在处理大量数据的时候使用数据库是明确的选择,在Android的开发中使用的数据库是SQLite ,它是一个轻量级的数据库 、非常小 、 移植性好、效率高、可靠 ,嵌入式设备因为受到硬件条件的限制所以非常适合使用 SQLite  数据库。

创建与删除数据库

        封装一个类去继承SQLiteOpenHelper  在构造函数中传入数据库名称与数据库版本号,数据库被创建的时候会调用onCreate(SQLiteDatabase db) 方法,数据库版本号发生改变的时候会调用onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法,可以方便的对软件游戏升级后做出相应处理避免覆盖安装数据库发生改变产生的错误。调用SQLiteOpenHelper  的getReadableDatabase()方法去创建数据库,如果数据库不存在则创建 并且返回SQLiteDatabase对象,如果数据库存在则不创建只返回SQLiteDatabase对象。调用deleteDatabase(DATABASE_NAME)方法 传入数据库名称则可删除数据库。

       封装了一个DatabaseHelper类继承SQLiteOpenHelper 我使用了设计模式中的单例模式来处理这个类,这里说一下单例模式 单例模式是常见的代码设计模式之一 它的好处是在于避免在内存中频繁的实例化所以将它的对象写成static 静态 这样它的对象就只有一份存在静态内存区使用的时候只须要通过getInstance()就可以直接拿到这个静态对象。
  1. public class DatabaseHelper extends SQLiteOpenHelper {
  2.     private static DatabaseHelper mInstance = null;

  3.     /** 数据库名称 **/
  4.     public static final String DATABASE_NAME = "xys.db";

  5.     /** 数据库版本号 **/
  6.     private static final int DATABASE_VERSION = 1;

  7.     /**数据库SQL语句 添加一个表**/
  8.     private static final String NAME_TABLE_CREATE = "create table test("
  9.             + "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+"hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"
  10.             + "number INTEGER);";

  11.     DatabaseHelper(Context context) {
  12.         super(context, DATABASE_NAME, null, DATABASE_VERSION);
  13.     }
  14.    
  15.      /**单例模式**/
  16.     static synchronized DatabaseHelper getInstance(Context context) {
  17.         if (mInstance == null) {
  18.             mInstance = new DatabaseHelper(context);
  19.         }
  20.         return mInstance;
  21.     }

  22.     @Override
  23.     public void onCreate(SQLiteDatabase db) {
  24.         /**向数据中添加表**/
  25.         db.execSQL(NAME_TABLE_CREATE);
  26.     }

  27.     @Override
  28.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  29.         /**可以拿到当前数据库的版本信息 与之前数据库的版本信息   用来更新数据库**/
  30.     }

  31.    
  32.     /**
  33.      * 删除数据库
  34.      * @param context
  35.      * @return
  36.      */
  37.     public boolean deleteDatabase(Context context) {
  38.         return context.deleteDatabase(DATABASE_NAME);
  39.     }
  40. }
复制代码
在这个类中使用DatabaseHelper对象 实现创建与删除数据库、
  1. public class NewSQLite extends Activity {
  2.     DatabaseHelper mDbHelper = null;
  3.     SQLiteDatabase mDb = null;
  4.     Context mContext = null;
  5.     @Override
  6.     protected void onCreate(Bundle savedInstanceState) {
  7.         setContentView(R.layout.create_sql);
  8.         mContext = this;
  9.         //创建DatabaseHelper对象      
  10.         mDbHelper = DatabaseHelper.getInstance(mContext);
  11.         //调用getReadableDatabase方法如果数据库不存在 则创建  如果存在则打开
  12.         mDb= mDbHelper.getReadableDatabase();  

  13.         Button button0 = (Button)findViewById(R.id.createDateBase);
  14.         button0.setOnClickListener(new OnClickListener() {
  15.             
  16.             @Override
  17.             public void onClick(View arg0) {

  18.                 Toast.makeText(NewSQLite.this, "成功创建数据库", Toast.LENGTH_LONG).show();  
  19.             }
  20.         });
  21.         Button button1 = (Button)findViewById(R.id.deleteDateBase);
  22.         button1.setOnClickListener(new OnClickListener() {
  23.             
  24.             @Override
  25.             public void onClick(View arg0) {
  26.                 mDbHelper = DatabaseHelper.getInstance(mContext);
  27.                 // 调用getReadableDatabase方法如果数据库不存在 则创建 如果存在则打开
  28.                 mDb = mDbHelper.getReadableDatabase();
  29.                 // 关闭数据库
  30.                 mDbHelper.close();
  31.                 // 删除数据库
  32.                 mDbHelper.deleteDatabase(mContext);
  33.                 Toast.makeText(NewSQLite.this, "成功删除数据库", Toast.LENGTH_LONG).show();  
  34.             }
  35.         });
  36.        
  37.        
  38.        
  39.         super.onCreate(savedInstanceState);
  40.     }

  41. }
复制代码
创建的数据库会被保存在当前项目中 databases 路径下 具体如图所示

添加与删除数据库中的表

        数据库是可以由多张数据表组成的 如果添加一张数据库的表的话 可以使用 数据库语句 create table 名称(内容) 来进行添加 。这里给出一条创建数据库的语句 。 意思是创建一张表 名称为gameInfo 表中包含的字段 为     _id  为INTEGER 类型 并且递增  name 为Text类型   hp mp 为INTEGER 默认数值为100 number 为INTEGER 类型。
  1.     /**创建一张表的SQL语句**/
  2.     private static final String NAME_TABLE_CREATE = "create table gameInfo("
  3.             + "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+ "hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"
  4.             + "number INTEGER);";
复制代码
数据库中删除一张表 直接使用DROP TABLE  表名称 就可以删除
  1.     /**删除一张表的SQL语句**/
  2.     private static final String NAME_TABLE_DELETE = "DROP TABLE gameInfo";
复制代码
在代码中去执行一条SQL语句 使用SQLiteDatabase对象去调用execSQL() 传入SQL语句就OK了。
  1. mDb.execSQL(NAME_TABLE_CREATE);
复制代码


以创建一张名称为gameInfo的表为例 给出代码实现
  1. public class NewTable extends Activity {
  2.     DatabaseHelper mDbHelper = null;
  3.     SQLiteDatabase mDb = null;
  4.     Context mContext = null;
  5.   
  6.     /**创建一张表的SQL语句**/
  7.     private static final String NAME_TABLE_CREATE = "create table gameInfo("
  8.             + "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+ "hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"
  9.             + "number INTEGER);";
  10.    
  11.    
  12.     /**删除一张表的SQL语句**/
  13.     private static final String NAME_TABLE_DELETE = "DROP TABLE gameInfo";
  14.    
  15.    
  16.     @Override
  17.     protected void onCreate(Bundle savedInstanceState) {
  18.         setContentView(R.layout.create_table);
  19.         mContext = this;
  20.         mDbHelper = DatabaseHelper.getInstance(mContext);
  21.         mDb= mDbHelper.getReadableDatabase();  
  22.        
  23.         Button button0 = (Button)findViewById(R.id.createTable);
  24.         button0.setOnClickListener(new OnClickListener() {
  25.             
  26.             @Override
  27.             public void onClick(View arg0) {
  28.                 try {
  29.                     mDb.execSQL(NAME_TABLE_CREATE);
  30.                     Toast.makeText(NewTable.this, "成功添加数据表", Toast.LENGTH_LONG).show();  
  31.                 }catch(SQLiteException e) {
  32.                     Toast.makeText(NewTable.this, "数据库中已存此表", Toast.LENGTH_LONG).show();   
  33.                 }
  34.             }
  35.         });
  36.         Button button1 = (Button)findViewById(R.id.deleteTable);
  37.         button1.setOnClickListener(new OnClickListener() {
  38.             
  39.             @Override
  40.             public void onClick(View arg0) {
  41.                 try {
  42.                     mDb.execSQL(NAME_TABLE_DELETE);
  43.                     Toast.makeText(NewTable.this, "成功删除数据表", Toast.LENGTH_LONG).show();
  44.                 }catch(SQLiteException e) {
  45.                     Toast.makeText(NewTable.this, "数据库中已无此表", Toast.LENGTH_LONG).show();   
  46.                 }

  47.             }
  48.         });
  49.        
  50.        
  51.        
  52.         super.onCreate(savedInstanceState);
  53.     }

  54. }
复制代码
增加 删除 修改 查询 数据库中的数据

使用SQLiteDatabase对象调用 insert()方法 传入标的名称与ContentValues 添加的内容 则可以向数据库表中写入一条数据 delete ()为删除一条数据 update()为更新一条数据。

我详细说一下查找一条数据使用的方法 query 中 跟了8个参数
public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit);
参数说明:
table:数据库表的名称
columns:数据库列名称数组 写入后最后返回的Cursor中只能查到这里的列的内容
selection:查询条件
selectionArgs:查询结果
groupBy:分组列
having:分组条件
orderBy:排序列
limit:分页查询限制
Cursor:返回值,将查询到的结果都存在Cursor
Cursor是一个游标接口,每次查询的结果都会保存在Cursor中 可以通过遍历Cursor的方法拿到当前查询到的所有信息。
Cursor的方法
moveToFirst() //将Curor的游标移动到第一条
moveToLast()///将Curor的游标移动到最后一条
move(int offset)//将Curor的游标移动到指定ID
moveToNext()//将Curor的游标移动到下一条
moveToPrevious()//将Curor的游标移动到上一条
getCount() //得到Cursor 总记录条数
isFirst() //判断当前游标是否为第一条记录
isLast()//判断当前游标是否为最后一条数据
getInt(int columnIndex)    //根据列名称获得列索引ID
getString(int columnIndex)//根据索引ID 拿到表中存的字段


这里给出一个例子遍历Cursor的例子
  1.     private void query(SQLiteDatabase db) {
  2.         // 把整张表的所有数据query到cursor中
  3.         Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null);
  4.         //判断cursor不为空 这个很重要
  5.         if (cursor != null) {
  6.             // 循环遍历cursor
  7.             while (cursor.moveToNext()) {
  8.                 // 拿到每一行name 与hp的数值
  9.                 String name = cursor.getString(cursor.getColumnIndex("name"));
  10.                 String hp = cursor.getString(cursor.getColumnIndex("hp"));
  11.                 Log.v("info", "姓名是 " + name + "hp为 " + hp);
  12.             }
  13.             // 关闭
  14.             cursor.close();
  15.         }
  16.     }
复制代码
向大家推荐一个查看数据库的软件非常好用, 名称是SQLiteSpy.exe  如图所示 打开xys.db 文件 可以清晰的看见数据库表中储存的内容并且该软件支持执行SQL语句 可以直接在软件中操作,我给出这款软件的下载地址。

下载地址:
  1. public class Newdate extends Activity {
  2.     DatabaseHelper mDbHelper = null;
  3.     SQLiteDatabase mDb = null;
  4.     Context mContext = null;

  5.     /** 数据库字段 **/

  6.     public final static String TABLE_NAME = "test";
  7.     public final static String ID = "_id";
  8.     public final static String NAME = "name";
  9.     public final static String HP = "hp";
  10.     public final static String MP = "mp";

  11.     @Override
  12.     protected void onCreate(Bundle savedInstanceState) {
  13.         setContentView(R.layout.create_date);
  14.         mContext = this;
  15.         // 创建DatabaseHelper对象
  16.         mDbHelper = DatabaseHelper.getInstance(mContext);
  17.         // 调用getReadableDatabase方法如果数据库不存在 则创建 如果存在则打开
  18.         mDb = mDbHelper.getReadableDatabase();
  19.         // 初始化 给数据库表写入一些信息
  20.         for (int i = 0; i < 10; i++) {
  21.             insert(NAME, "雨松MOMO" + i);
  22.         }

  23.         // 增加
  24.         Button button0 = (Button) findViewById(R.id.add);
  25.         button0.setOnClickListener(new OnClickListener() {

  26.             @Override
  27.             public void onClick(View arg0) {
  28.                 insert(NAME, "新添加小可爱");
  29.                 Toast.makeText(Newdate.this, "添加一条数据名称为小可爱", Toast.LENGTH_LONG)
  30.                         .show();
  31.             }
  32.         });
  33.         // 删除
  34.         Button button1 = (Button) findViewById(R.id.delete);
  35.         button1.setOnClickListener(new OnClickListener() {

  36.             @Override
  37.             public void onClick(View arg0) {
  38.                 delete(ID, "1");
  39.                 Toast.makeText(Newdate.this, "删除一条_id=1的数据", Toast.LENGTH_LONG)
  40.                         .show();
  41.             }
  42.         });
  43.         // 修改
  44.         Button button2 = (Button) findViewById(R.id.modify);
  45.         button2.setOnClickListener(new OnClickListener() {

  46.             @Override
  47.             public void onClick(View arg0) {
  48.                 update(NAME, "雨松MOMO3", "小可爱3");
  49.                 Toast.makeText(Newdate.this, "更新名称雨松MOMO3 为小可爱3",
  50.                         Toast.LENGTH_LONG).show();
  51.             }
  52.         });
  53.         // 查找
  54.         Button button3 = (Button) findViewById(R.id.find);
  55.         button3.setOnClickListener(new OnClickListener() {

  56.             @Override
  57.             public void onClick(View arg0) {
  58.                 Cursor cursor = find(ID, "5");
  59.                 String name = cursor.getString(cursor.getColumnIndex(NAME));
  60.                 Toast.makeText(Newdate.this, "查找ID为5数据的名称是 " + name,
  61.                         Toast.LENGTH_LONG).show();
  62.             }
  63.         });
  64.         super.onCreate(savedInstanceState);
  65.     }

  66.     /**
  67.      * 插入一条数据
  68.      *
  69.      * @param key
  70.      * @param date
  71.      */
  72.     public void insert(String key, String date) {
  73.         ContentValues values = new ContentValues();
  74.         values.put(key, date);
  75.         mDb.insert(TABLE_NAME, null, values);
  76.     }

  77.     /**
  78.      * 删除一掉数据
  79.      *
  80.      * @param key
  81.      * @param date
  82.      */
  83.     public void delete(String key, String date) {
  84.         mDb.delete(TABLE_NAME, key + "=?", new String[] { date });
  85.     }

  86.     /**
  87.      * 更新一条数据
  88.      *
  89.      * @param key
  90.      * @param oldDate
  91.      * @param newDate
  92.      */
  93.     public void update(String key, String oldDate, String newDate) {
  94.         ContentValues values = new ContentValues();
  95.         values.put(key, newDate);
  96.         mDb.update(TABLE_NAME, values, key + "=?", new String[] { oldDate });
  97.     }

  98.     /**
  99.      * 查找一条数据
  100.      *
  101.      * @param key
  102.      * @param date
  103.      * @return
  104.      */
  105.     public Cursor find(String key, String date) {

  106.         Cursor cursor = mDb.query(TABLE_NAME, null, key + "=?",
  107.                 new String[] { date }, null, null, null);
  108.         if (cursor != null) {
  109.             cursor.moveToFirst();
  110.         }
  111.         return cursor;
  112.     }

  113. }
复制代码
这里我在强调一下query中的第二个参数String [] columns , 举个例子 当前在数据中query 数值 如果我只想要数据中符合条件数据每一行的name字段和hp 字段 那么第二个参数就不要写成null了。

第二个参数我写成了new String[] {"name","hp"} 这样的话得到的Cursor 中的数据只会存有 数据库表中"name " 与 "hp"两个字段 因为其它字段我们根本不需要所以着么写可以大大提高代码的效率。如果写成null的话 Cursor 中的数据就会把数据库表中所以的字段都保存进去这样在计算Cursor 的时候代码就会消耗更多没用的时间。

cursor.getString(0); 的意思就是拿到对应new String[] {"name","hp"} 数组中的一个字段的内容 意思就是拿到 数据库字段"name"的值, cursor.getString(1);的意思就是拿到数据库字段"hp"的值 。cursor.getString()中的ID 是完全对应第二个参数String [] columns数组角标。
  1.     public void find() {
  2.         Cursor cursor = mDb.query(TABLE_NAME, new String[] {"name","hp"}, null,
  3.                 null, null, null, null);
  4.         while(cursor.moveToNext()) {
  5.             String name = cursor.getString(0);
  6.             String hp = cursor.getString(1);
  7.             Log.v("info", "name is "+name);
  8.             Log.v("info", "hp is "+hp);
  9.         }
  10.     }
复制代码
最后如果你还是觉得我写的不够详细 看的不够爽 不要紧我把源代码的下载地址贴出来 欢迎大家一起讨论学习

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

点评

讲得很详细  发表于 2013-3-19 15:23
hen hao  发表于 2013-3-1 11:00

0

主题

6

帖子

13

安币

初级码农

Rank: 1

发表于 2011-9-6 23:22:54 | 显示全部楼层
非常有用啊,顶起。

14

主题

361

帖子

204

安币

攻城狮

Rank: 3Rank: 3

发表于 2011-9-7 14:46:44 | 显示全部楼层
Android游戏开发之数据库SQLite 详细介绍(十七)

14

主题

361

帖子

204

安币

攻城狮

Rank: 3Rank: 3

发表于 2011-9-7 14:46:57 | 显示全部楼层
Android游戏开发之数据库SQLite 详细介绍(十七)

14

主题

361

帖子

204

安币

攻城狮

Rank: 3Rank: 3

发表于 2011-9-7 14:47:11 | 显示全部楼层
Android游戏开发之数据库SQLite 详细介绍(十七)

0

主题

74

帖子

144

安币

程序猿

Rank: 2

发表于 2011-9-12 15:46:59 | 显示全部楼层
good,i like it

0

主题

74

帖子

144

安币

程序猿

Rank: 2

发表于 2011-9-12 15:50:21 | 显示全部楼层
很好,很喜欢,顶起!

1

主题

25

帖子

12

安币

初级码农

Rank: 1

发表于 2011-9-13 13:31:34 | 显示全部楼层
。。。哈哈 这个非常好  下下来看看。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )