数据存储
文件存储
将数据存储到文件中
private fun save(inputText: String) {
try {
// 通过openFileOutput方法得到FileOutputStream对象
// 第一个参数为文件名,不可以包含路径,因为默认存放在/data/data/<package name>/files/目录下
// 第二个参数时文件的操作模式,主要有MODE_PRIVATE和MODE_APPEND两种,默认为MODE_PRIVATE
// MODE_PRIVATE表示相同文件名时会覆盖原文件。
// MODE_APPEND表示存在就向其追加内容,否则就创建新文件
val output = openFileOutput("data", Context.MODE_PRIVATE)
// 使用OutputStreamWriter构建出BufferedWriter对象,这样就可以向其中写入文件了
val writer = BufferedWriter(OutputStreamWriter(output))
writer.use {
it.write(inputText)
}
} catch (e: IOException) {
e.printStackTrace()
}
}
借助右下角的Device File Explorer工具查看
从文件中读取数据
private fun load(): String {
val content = StringBuilder()
try {
val input = openFileInput("data")
val reader = BufferedReader(InputStreamReader(input))
reader.use {
reader.forEachLine {
content.append(it)
}
}
} catch (e: IOException) {
e.printStackTrace()
}
return content.toString()
}
SharedPreferences
SharedPreferences是使用键值对的方式来存储数据的。
将数据存储到SharedPreferences
获取SharedPreferences有两种方法
- Context类中的getSharedPreferences方法
此方法接受两个参数:文件名称,如果不存在则创建,SharedPreferences的文件都存放在/data/data/<package name>/shared_prefs
目录下。操作模式,目前只有默认的MODE_PRIVATE可选,直接输入0效果相同,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。 - Activity类中的getPreferences方法
与Context类中的getSharedPreferences方法类似,但只接受一个参数,因为其自动将当前Activity的类名作为SharedPreferences的文件名。
得到SharedPreferences对象后,就可以开始存储数据了,主要可以分为三步实现: - 调用SharedPreferences对象的edit方法获取一个SharedPreferences.Editor对象。
- 向SharedPreferences.Editor对象中添加数据,比如字符串就使用putString方法,以此类推。第一个参数为键值,第二个为数据内容。
- 调用apply方法将添加的数据提交。
val editor = getSharedPreferences("data", Context.MODE_PRIVATE).edit()
editor.putString("name", "Tom")
editor.putInt("age", 28)
editor.putBoolean("married", false)
editor.apply()
从SharedPreferences中读取数据
SharedPreferences的每一个put方法都有对应的get方法。第一个参数为键值,第二个为默认值。
val prefs = getSharedPreferences("data", Context.MODE_PRIVATE)
val name = prefs.getString("name", "")
val age = prefs.getInt("age", 0)
val married = prefs.getBoolean("married", false)
SQLite数据库存储
SQLite是一款轻量级的关系型数据库,运算速度非常快,占用资源很少。
创建数据库
Android提供了一个SQLiteOpenHelper帮助类来管理数据库。
SQLiteOpenHelper是一个抽象类,使用它要先创建一个类去继承它。并重写它的两个抽象方法:onCreate和onUpgrade方法,在它们中分别实现创建和升级数据库的逻辑。
SQLiteOpenHelper有两个重要的实例方法。它们都可以创建或打开一个数据库,并返回一个可对数据库进行操作的对象。不同的是,当数据库不可写入时,getReadableDatabase返回的对象将以只读形式打开,而getWritableDatabase将出现异常。
SQLiteOpenHelper中有两个构造方法可供重写,一般使用参数少一点的那个即可。这个构造方法接收四个参数:Context、数据库名、允许我们返回一个自定义的Cursor,一般传入null即可、表示当前数据库版本号,可用于对数据库升级。数据库文件会存放在/data/data/<package name>/databases
。
从Android Studio导航栏中打开Preferences->Plugins,下载Database Navigator,用来查看.db文件。
新建数据库
class MyDatabaseHelper(val context: Context, name: String, version: Int) : SQLiteOpenHelper(context, name, null, version) {
// integer表示整型、text表示文本类型、real表示浮点数
// primary key将id设为主键,autoincrement表示id是自增长的
private val createBook = "create table Book (" +
" id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text," +
"category_id integer)"
private val createCategory = "create table Category (" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)"
override fun onCreate(db: SQLiteDatabase) {
db.execSQL(createBook)
db.execSQL(createCategory)
Toast.makeText(context, "Create succeeded", Toast.LENGTH_SHORT).show()
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
// 判断版本执行相应操作
if (oldVersion <= 1) {
db.execSQL(createCategory)
}
if (oldVersion <= 2) {
db.execSQL("alter table Book add column category_id integer")
}
}
}
在Activity中执行操作
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val dbHelper = MyDatabaseHelper(this, "BookStore.db", 3)
createDatabase.setOnClickListener {
dbHelper.writableDatabase
}
contentValuesOf("" to "")
// 添加数据
addData.setOnClickListener {
val db = dbHelper.writableDatabase
val values1 = ContentValues().apply {
// 开始组装第一条数据
put("name", "The Da Vinci Code")
put("author", "Dan Brown")
put("pages", 454)
put("price", 16.96)
}
db.insert("Book", null, values1) // 插入第一条数据
val values2 = ContentValues().apply {
// 开始组装第二条数据
put("name", "The Lost Symbol")
put("author", "Dan Brown")
put("pages", 510)
put("price", 19.95)
}
db.insert("Book", null, values2) // 插入第二条数据
}
// 更新数据
updateData.setOnClickListener {
val db = dbHelper.writableDatabase
val values = ContentValues()
values.put("price", 10.99)
val rows = db.update("Book", values, "name = ?", arrayOf("The Da Vinci Code"))
Toast.makeText(this, "rows is $rows", Toast.LENGTH_SHORT).show()
}
// 删除数据
deleteData.setOnClickListener {
val db = dbHelper.writableDatabase
db.delete("Book", "pages > ?", arrayOf("500"))
}
// 查询数据
queryData.setOnClickListener {
val db = dbHelper.writableDatabase
// 查询Book表中所有的数据
val cursor = db.query("Book", null, null, null, null, null, null)
if (cursor.moveToFirst()) {
do {
// 遍历Cursor对象,取出数据并打印
val name = cursor.getString(cursor.getColumnIndex("name"))
val author = cursor.getString(cursor.getColumnIndex("author"))
val pages = cursor.getInt(cursor.getColumnIndex("pages"))
val price = cursor.getDouble(cursor.getColumnIndex("price"))
Log.d("MainActivity", "book name is $name")
Log.d("MainActivity", "book author is $author")
Log.d("MainActivity", "book pages is $pages")
Log.d("MainActivity", "book price is $price")
} while (cursor.moveToNext())
}
cursor.close()
}
replaceData.setOnClickListener {
val db = dbHelper.writableDatabase
db.beginTransaction() // 开启事务
try {
db.delete("Book", null, null)
// if (true) {
// // 在这里手动抛出一个异常,让事务失败
// throw NullPointerException()
// }
val values = cvOf("name" to "Game of Thrones", "author" to "George Martin", "pages" to 720, "price" to 20.85)
db.insert("Book", null, values)
db.setTransactionSuccessful() // 事务已经执行成功
} catch (e: Exception) {
e.printStackTrace()
} finally {
db.endTransaction() // 结束事务
}
}
}
}
对应activity_main.xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/createDatabase"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Database"
/>
<Button
android:id="@+id/addData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Data"
/>
<Button
android:id="@+id/updateData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update Data"
/>
<Button
android:id="@+id/deleteData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete Data"
/>
<Button
android:id="@+id/queryData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query Data"
/>
<Button
android:id="@+id/replaceData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Replace Data"
/>
</LinearLayout>