一 SharedPreferences
- SharedPreferences是使用键值对的方式来存储数据的。数据保存在一个xml文件中,在/data/data/<package_name>/shared_prefs目录下。
- 要想使用SharedPreferences存储数据,首先需要获取SharedPreferences对象。Android提供了以下两种方法用于得到SharedPreferences对象。
- Context类中的getSharedPreferences()方法:
此方法接收两个参数:第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个;第二个参数用于指定操作模式,目前只有默认的MODE_PRIVATE这一种模式可选,其它已废弃,MODE_PRIVATE表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。
- Activity类中的getPreferences()方法
这个方法和第一种类似,不过它只接收一个操作模式参数,因为使用这个方法时会自动将当前Activity的类名作为SharedPreferences的文件名。
- 得到SharedPreferences对象之后,就可以开始向SharedPreferences文件中存储数据了,主要步骤如下:
- 调用SharedPreferences对象的
edit()
方法获取一个SharedPreferences.Editor对象。 - 向SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用
putBoolean()
方法。 - 调用
apply()
方法将添加的数据提交,从而完成数据存储操作。
sendBtn.setOnClickListener {
val editor = getSharedPreferences("student", Context.MODE_PRIVATE).edit()
editor.putString("name", "yangzhiyang")
editor.putInt("age", 18)
editor.apply()
}
从SharedPreferences中读取数据
val prefs = getSharedPreferences("student",Context.MODE_PRIVATE)
val name = prefs.getString("name", "")
val age = prefs.getInt("age", 0)
二 SQLite数据库存储
- 创建数据库
- Android为了更方便管理数据库,专门提供了一个SQLiteOpenHelper帮助类,借助这个类可以非常简单的对数据库进行创建和升级。
SQLiteOpenHelper 是一个抽象类,想使用它需要创建一个自己的帮助类去继承它。并实现两个抽象方法:onCreate()和onUpgrade()。然后分别在这两个方法中实现创建和升级数据库的逻辑。
SQLiteOpenHelper有两个非常重要的实例方法:getReadableDatabase()和getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则要创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式打开数据库,而getWritableDatabase()方法则将抛出异常。
- 自定义数据库
class MyDatabaseHelper(val context: Context, val name: String, val version: Int)
: SQLiteOpenHelper(context,name,null,version) {
private val createBook = "create table Book (" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)"
override fun onCreate(db: SQLiteDatabase?) {
db?.execSQL(createBook)
Toast.makeText(context, "Create successed", Toast.LENGTH_SHORT).show()
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
TODO("Not yet implemented")
}
}
- 创建
class MainActivity : BaseActivity() {
private lateinit var sendBtn: Button
private lateinit var dbHelper: MyDatabaseHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
setListener()
}
private fun setListener() {
sendBtn.setOnClickListener {
dbHelper.writableDatabase
}
}
private fun initView() {
sendBtn = findViewById(R.id.createDatabase)
dbHelper = MyDatabaseHelper(this,"BookStore.db",1)
}
}
- 升级数据库
假设目前已经有了BookStore.db数据库,里面有一张Book表,如果我们想再添加一张Category表用于记录图书的分类,该怎么做呢?
在onUpgrade()方法中执行Drop语句,如果发现数据库中已经存在某张表,就删除,然后再调用onCreate()方法重新创建。
SQLiteOpenHelper的构造函数第四个参数接收当前数据库版本号,现在只要传入比之前大的版本就能执行onUpgrage。
class MyDatabaseHelper(val context: Context, val name: String, val version: Int)
: SQLiteOpenHelper(context,name,null,version) {
private val createBook = "create table Book (" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)"
private val category = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)"
override fun onCreate(db: SQLiteDatabase?) {
db?.execSQL(createBook)
db?.execSQL(category)
Toast.makeText(context, "Create successed", Toast.LENGTH_SHORT).show()
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
db?.execSQL("drop table if exists Book")
db?.execSQL("drop table if exists Category")
onCreate(db)
}
}
- 添加数据
insertBtn.setOnClickListener {
val sqliteDatabase: SQLiteDatabase = dbHelper.writableDatabase
val value1 = ContentValues().apply {
put("name", "A")
put("author","yzy")
put("pages",200)
put("price",27)
}
sqliteDatabase.insert("Book", null,value1)
val value2 = ContentValues().apply {
put("name", "A")
put("author","lp")
put("pages",200)
put("price",27)
}
sqliteDatabase.insert("Book", null, value2)
}
- 更新数据
updateBtn.setOnClickListener {
val sqLiteDatabase: SQLiteDatabase = dbHelper.writableDatabase
val value = ContentValues().apply {
put("price", 10)
}
sqLiteDatabase.update("Book",value,"name = ?", arrayOf("A"))
sqLiteDatabase.close()
}
- 删除数据
deleteBtn.setOnClickListener {
val sqLiteDatabase = dbHelper.writableDatabase
sqLiteDatabase.delete("Book", "name = ?", arrayOf("A"))
sqLiteDatabase.close()
}
- 查询数据
queryBtn.setOnClickListener {
val sqLiteDatabase = dbHelper.writableDatabase
val cursor = sqLiteDatabase.query("Book", arrayOf("name","author"),"name = ? and author = ?", arrayOf("B","lp"),null,null,null)
if (cursor.moveToFirst()){
do {
//遍历cursor对象 取出数据
val name = cursor.getString(cursor.getColumnIndex("name"))
val author = cursor.getString(cursor.getColumnIndex("author"))
Log.e(TAG, "name-->$name")
Log.e(TAG,"author-->$author")
}while (cursor.moveToNext());
}
}
三 使用SQL操作数据库
- 添加数据
val insert = "insert into Book (name, author, pages, price) values(?,?,?,?)";
val sqLiteDatabase = dbHelper.writableDatabase
sqLiteDatabase.execSQL(insert, arrayOf("MyHeart", "Yan", "500", "27"))
- 更新数据
val update = "update Book set price=? where name=?";
sqLiteDatabase.execSQL(update, arrayOf("999", "MyHeart"))
- 删除数据
val delete = "delete from Book where name=?";
sqLiteDatabase.execSQL(delete, arrayOf("MyHeart"))
- 查询数据
val query = "select * from Book where name = ?";
sqLiteDatabase.execSQL(query, arrayOf("MyHeart"))
四 升级数据库最佳写法
每一个数据库版本都会对应一个版本号,当指定的数据库版本号大于当前数据库版本号的时候,就会进入onUpgrade()方法中执行更新操作。
- 下面模拟一个数据库升级
- 第一版的程序只需要创建一张Book表
class MyDatabaseHelper(val context: Context, val name: String, val version: Int)
: SQLiteOpenHelper(context,name,null,version) {
private val createBook = "create table Book (" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)"
override fun onCreate(db: SQLiteDatabase?) {
db?.execSQL(createBook)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
}
}
- 第二版需要向数据库中再添加一张Category表
如果用户数据库的旧版本号小于等于1,就只会创建一张Category表。
当用户直接安装第二版的程序时,就会进入onCreate()方法,将两张表一起创建。
而当用户使用第二版的程序覆盖安装第一版的程序时,就会进入升级数据库的操作中,此时由于Book表已经存在了,因此只需要创建一张Category表即可。
class MyDatabaseHelper(val context: Context, val name: String, val version: Int)
: SQLiteOpenHelper(context,name,null,version) {
private val createBook = "create table Book (" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)"
private val category = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)"
override fun onCreate(db: SQLiteDatabase?) {
db?.execSQL(createBook)
db?.execSQL(category)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
if (oldVersion <= 1){
db?.execSQL(category)
}
}
}
- 第三版需要给Book表和Category表之间建立关联,需要在Book表中添加一个category_id字段。
首先在Book表中添加了一列,这样当用户直接安装第三版程序时,这个新增列就已经自动添加成功。
然而,当用户之前已经安装了某一版本程序,现在需要覆盖安装,就会进入升级数据库的操作中。在onUpgrade()方法里,判断如果当前数据库的版本号是2,就会执行alter命令,为Book表新增一列。
class MyDatabaseHelper(val context: Context, val name: String, val version: Int)
: SQLiteOpenHelper(context,name,null,version) {
private val createBook = "create table Book (" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text," +
"category_id integer)"
private val category = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)"
override fun onCreate(db: SQLiteDatabase?) {
db?.execSQL(createBook)
db?.execSQL(category)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
if (oldVersion <= 1){
db?.execSQL(category)
}
if (oldVersion <= 2){
db?.execSQL("alter table Book add column category_id integer")
}
}
}