【Android游戏开发十三】(保存游戏数据 [下文])详解SQLite存储方式,并把SQLite的数据库文件存储在SD卡中!!!

2019年12月05日 阅读数:131
这篇文章主要向大家介绍【Android游戏开发十三】(保存游戏数据 [下文])详解SQLite存储方式,并把SQLite的数据库文件存储在SD卡中!!!,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

上一篇跟各位童鞋介绍了SharedPreference 和 File流如何存储数据,而且推荐使用FileOutputStream/FileInputStream来存储我们游戏数据,那么这一篇则是像你们介绍另一种适合游戏数据存储的方式:SQLite 轻量级数据库!java

先介绍几个基本概念知识:mysql

什么是SQLite:android

SQLite是一款轻量级数据库,它的设计目的是嵌入式,并且它占用的资源很是少,在嵌入式设备中,只须要几百KB!!!!!sql

SQLite的特性:数据库

  • 轻量级
    使用 SQLite 只须要带一个动态库,就能够享受它的所有功能,并且那个动态库的尺寸想当小。
  • 独立性
    SQLite 数据库的核心引擎不须要依赖第三方软件,也不须要所谓的“安装”。
  • 隔离性
    SQLite 数据库中全部的信息(好比表、视图、触发器等)都包含在一个文件夹内,方便管理和维护。
  • 跨平台
    SQLite 目前支持大部分操做系统,不至电脑操做系统更在众多的手机系统也是可以运行,好比:Android。
  • 多语言接口
    SQLite 数据库支持多语言编程接口。
  • 安全性
    SQLite 数据库经过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程能够在同一时间从同一数据库读取数据,但只能有一个能够写入数据.

优势:1.能存储较多的数据。编程

2.能将数据库文件存放到SD卡中!安全

什么是 SQLiteDatabase? app

一个 SQLiteDatabase 的实例表明了一个SQLite 的数据库,经过SQLiteDatabase 实例的一些方法,咱们能够执行SQL 语句,对数        据库进行增、删、查、改的操做。须要注意的是,数据库对于一个应用来讲是私有的,而且在一个应用当中,数据库的名字也是唯一的。ide

什么是 SQLiteOpenHelper ?函数

根据这名字,咱们能够看出这个类是一个辅助类。这个类主要生成一个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的        方法getWritableDatabase(),或者getReadableDatabase()方法的时候,若是当时没有数据,那么Android 系统就会自动生成一        个数  据库。SQLiteOpenHelper 是一个抽象类,咱们一般须要继承它,而且实现里边的3 个函数,

什么是 ContentValues 类?

ContentValues 类和Hashmap/Hashtable 比较相似,它也是负责存储一些名值对,可是它存储的名值对当中的名是一个

String 类型,而值都是基本类型。

什么是 Cursor ?

Cursor 在Android 当中是一个很是有用的接口,经过Cursor 咱们能够对从数据库查询出来的结果集进行随  机的读写访问。

OK,基本知识就介绍到这里,下面开始上代码:仍是按照个人一向风格,代码中该解释的地方都已经在代码中及时注释和讲解了!

顺便来张项目截图:

先给出xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version= "1.0" encoding= "utf-8" ?>
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
     android:orientation= "vertical" android:layout_width= "fill_parent"
     android:layout_height= "fill_parent" >
     <TextView android:layout_width= "fill_parent"
         android:layout_height= "wrap_content" android:text= "SQL 练习!(若是你使用的SD卡存储数据方式,为了保证正常操做,请你先点击建立一张表而后再操做)"
         android:textSize= "20sp" android:textColor= "#ff0000" android:id= "@+id/tv_title" />
     <Button android:id= "@+id/sql_addOne" android:layout_width= "fill_parent"
         android:layout_height= "wrap_content" android:text= "插入一条记录" ></Button>
     <Button android:id= "@+id/sql_check" android:layout_width= "fill_parent"
         android:layout_height= "wrap_content" android:text= "查询数据库" ></Button>
     <Button android:id= "@+id/sql_edit" android:layout_width= "fill_parent"
         android:layout_height= "wrap_content" android:text= "修改一条记录" ></Button>
     <Button android:id= "@+id/sql_deleteOne" android:layout_width= "fill_parent"
         android:layout_height= "wrap_content" android:text= "删除一条记录" ></Button>
     <Button android:id= "@+id/sql_deleteTable" android:layout_width= "fill_parent"
         android:layout_height= "wrap_content" android:text= "删除数据表单" ></Button>
     <Button android:id= "@+id/sql_newTable" android:layout_width= "fill_parent"
         android:layout_height= "wrap_content" android:text= "新建数据表单" ></Button>
</LinearLayout>

xml中定义了咱们须要练习用到的几个操做按钮,这里很少解释了,下面看java源码:先看咱们继承的 SQLiteOpenHelper 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.himi;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
  *
  * @author Himi
  * @解释 此类咱们只须要传建一个构造函数 以及重写两个方法就OK啦、
  *
  */
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
     public final static int VERSION = 1 ; // 版本号
     public final static String TABLE_NAME = "himi" ; // 表名
     public final static String ID = "id" ; // 后面ContentProvider使用
     public final static String TEXT = "text" ;
     public static final String DATABASE_NAME = "Himi.db" ;
     public MySQLiteOpenHelper(Context context) {
         // 在Android 中建立和打开一个数据库均可以使用openOrCreateDatabase 方法来实现,
         // 由于它会自动去检测是否存在这个数据库,若是存在则打开,不过不存在则建立一个数据库;
         // 建立成功则返回一个 SQLiteDatabase对象,不然抛出异常FileNotFoundException。
         // 下面是来建立一个名为"DATABASE_NAME"的数据库,并返回一个SQLiteDatabase对象  
 
         super (context, DATABASE_NAME, null , VERSION);
     }
     @Override
     // 在数据库第一次生成的时候会调用这个方法,通常咱们在这个方法里边生成数据库表;
     public void onCreate(SQLiteDatabase db) {
         String str_sql = "CREATE TABLE " + TABLE_NAME + "(" + ID
                 + " INTEGER PRIMARY KEY AUTOINCREMENT," + TEXT + " text );" ;
         // CREATE TABLE 建立一张表 而后后面是咱们的表名
         // 而后表的列,第一个是id 方便操做数据,int类型
         // PRIMARY KEY 是指主键 这是一个int型,用于惟一的标识一行;
         // AUTOINCREMENT 表示数据库会为每条记录的key加一,确保记录的惟一性;
         // 最后我加入一列文本 String类型
         // ----------注意:这里str_sql是sql语句,相似dos命令,要注意空格!
         db.execSQL(str_sql);
         // execSQL()方法是执行一句sql语句
         // 虽然此句咱们生成了一张数据库表和包含该表的sql.himi文件,
         // 可是要注意 不是方法是建立,是传入的一句str_sql这句sql语句表示建立!!
     }
     @Override
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
         // 通常默认状况下,当咱们插入 数据库就当即更新
         // 当数据库须要升级的时候,Android 系统会主动的调用这个方法。
         // 通常咱们在这个方法里边删除数据表,并创建新的数据表,
         // 固然是否还须要作其余的操做,彻底取决于游戏需求。
         Log.v( "Himi" , "onUpgrade" );
     }
}

我喜欢代码中当即附上解释,感受这样代码比较让你们更容易理解和寻找,固然若是童鞋们不喜欢,能够告诉我,我改~嘿嘿~

下面看最重要的MainActivity中的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package com.himi;
import java.io.File;
import java.io.IOException;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
// ------------第三种保存方式--------《SQLite》---------
/**
  * @author Himi
  * @保存方式:SQLite 轻量级数据库、
  * @优势: 能够将本身的数据存储到文件系统或者数据库当中, 也能够将本身的数据存
  *         储到SQLite数据库当中,还能够存到SD卡中
  * @注意1:数据库对于一个游戏(一个应用)来讲是私有的,而且在一个游戏当中,
  *         数据库的名字也是惟一的。
  * @注意2 apk中建立的数据库外部的进程是没有权限去读/写的,
  *         咱们须要把数据库文件建立到sdcard上能够解决相似问题.
  * @注意3 当你删除id靠前的数据或者所有删除数据的时候,SQLite不会自动排序,
  *        也就是说再添加数据的时候你不指定id那么SQLite默认仍是在原有id最后添加一条新数据
  * @注意4 android 中 的SQLite 语法大小写不敏感,也就是说不区分大小写;
  *
  */
public class MainActivity extends Activity implements OnClickListener {
     private Button btn_addOne, btn_deleteone, btn_check, btn_deleteTable,
             btn_edit, btn_newTable;
     private TextView tv;
     private MySQLiteOpenHelper myOpenHelper; // 建立一个继承SQLiteOpenHelper类实例
     private SQLiteDatabase mysql ;
//---------------如下两个成员变量是针对在SD卡中存储数据库文件使用
//  private File path = new File("/sdcard/himi");// 建立目录
//  private File f = new File("/sdcard/himi/himi.db");// 建立文件
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                 WindowManager.LayoutParams.FLAG_FULLSCREEN);
         this .requestWindowFeature(Window.FEATURE_NO_TITLE);
         setContentView(R.layout.main);
         tv = (TextView) findViewById(R.id.tv_title);
         btn_addOne = (Button) findViewById(R.id.sql_addOne);
         btn_check = (Button) findViewById(R.id.sql_check);
         btn_deleteone = (Button) findViewById(R.id.sql_deleteOne);
         btn_deleteTable = (Button) findViewById(R.id.sql_deleteTable);
         btn_newTable = (Button) findViewById(R.id.sql_newTable);
         btn_edit = (Button) findViewById(R.id.sql_edit);
         btn_edit.setOnClickListener( this );
         btn_addOne.setOnClickListener( this );
         btn_check.setOnClickListener( this );
         btn_deleteone.setOnClickListener( this );
         btn_deleteTable.setOnClickListener( this );
         btn_newTable.setOnClickListener( this );
         myOpenHelper = new MySQLiteOpenHelper( this ); // 实例一个数据库辅助器
//备注1  ----若是你使用的是将数据库的文件建立在SD卡中,那么建立数据库mysql以下操做:
//      if (!path.exists()) {// 目录存在返回false
//          path.mkdirs();// 建立一个目录
//      }
//      if (!f.exists()) {// 文件存在返回false
//          try {
//              f.createNewFile();//建立文件
//          } catch (IOException e) {
//              // TODO Auto-generated catch block
//              e.printStackTrace();
//          }
//      }
     }
     @Override
     public void onClick(View v) {
         try {
//备注2----若是你使用的是将数据库的文件建立在SD卡中,那么建立数据库mysql以下操做:
//              mysql = SQLiteDatabase.openOrCreateDatabase(f, null);
//备注3--- 若是想把数据库文件默认放在系统中,那么建立数据库mysql以下操做:
                 mysql = myOpenHelper.getWritableDatabase(); // 实例数据库
             if (v == btn_addOne) { // 添加数据
                 // ---------------------- 读写句柄来插入---------
                 // ContentValues 其实就是一个哈希表HashMap, key值是字段名称,
                 //Value值是字段的值。而后 经过 ContentValues 的 put 方法就能够
                 //把数据放到ContentValues中,而后插入到表中去!
                 ContentValues cv = new ContentValues();
                 cv.put(MySQLiteOpenHelper.TEXT, "测试新的数据" );
                 mysql.insert(MySQLiteOpenHelper.TABLE_NAME, null , cv);
                 // inser() 第一个参数 标识须要插入操做的表名
                 // 第二个参数 :默认传null便可
                 // 第三个是插入的数据
                 // ---------------------- SQL语句插入--------------
                 // String INSERT_DATA =
                 // "INSERT INTO himi (id,text) values (1, '经过SQL语句插入')";
                 // db.execSQL(INSERT_DATA);
                 tv.setText( "添加数据成功!点击查看数据库查询" );
             } else if (v == btn_deleteone) { // 删除数据
                 // ---------------------- 读写句柄来删除
                 mysql.delete( "himi" , MySQLiteOpenHelper.ID + "=1" , null );
                 // 第一个参数 须要操做的表名
                 // 第二个参数为 id+操做的下标 若是这里咱们传入null,表示所有删除