持久化技术
文件存储、SharedPreference、数据库存储
文件存储
将数据存储到文件中
Context类提供了一个openFileOutput()方法,将数据存到指定文件中。返回一个FileOutpueStream对象。
两个参数:
文件名,不包含路径,因为所有文件都默认存储到/data/data/
文件的操作模式:MODE_PRIVATE(默认)和MPDE_APPEND。
MODE_PRIVATE:表示当指定相同文件名的时候,所写入的内容覆盖原文件。
MPDE_APPEND:追加。
openFilOutput()方法返回一个FileOutputStream对象
实例:
fun save(inputText: String) {
try {
val output = openFileOutput("data", Context.MODE_PRIVATE)
val writer = BufferedWriter(OutputStreamWriter(output))
writer.use {
it.write(inputText)
}
} catch (e: IOException) {
e.printStackTrace()
}
}
这里使用了一个use函数,他保证在Lambda表达式中的代码全部执行完之后自动将外层的流关闭,这样就不用再写finally
新建FilePersistenceTest项目,修改activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Type something here" />
</LinearLayout>
修改MainActivity代码:
package com.example.filepersistencetest
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import java.io.BufferedWriter
import java.io.IOException
import java.io.OutputStream
import java.io.OutputStreamWriter
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onDestroy() {
super.onDestroy()
val inputText = editText.toString()
save(inputText)
}
private fun save(inputText: String) {
try {
val output = openFileOutput("data", Context.MODE_PRIVATE)
val writer = BufferedWriter(OutputStreamWriter(output))
writer.use {
it.write(inputText)
}
} catch (e: IOException) {
e.printStackTrace()
}
}
}
从文件中读取数据
Context类提供了openFileInput()方法。
参数:要读取的文件名
返回一个FileInputStream对象。
例子:
package com.example.filepersistencetest
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import java.io.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intentText = load()
if (intentText.isNotEmpty()) {
editText.setText(intentText)
editText.setSelection(intentText.length)
Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show()
}
}
override fun onDestroy() {
super.onDestroy()
val inputText = editText.toString()
save(inputText)
}
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()
}
private fun save(inputText: String) {
try {
val output = openFileOutput("data", Context.MODE_PRIVATE)
val writer = BufferedWriter(OutputStreamWriter(output))
writer.use {
it.write(inputText)
}
} catch (e: IOException) {
e.printStackTrace()
}
}
}
调用了setSelection()方法将输入光标移动到文本的末尾位置
SharedPreferences存储
SharedPreferences是使用键值对存储数据的
将数据存储到SharedPreferences中
获得SharedPreferences对象
1.Context类中的getSharedPreferences()方法
参数:1.指定SharedPreferences文件名称,SharedPreferences文件存放在/data/data/
2.Activity类中的getPreferences()方法
只接收一个操作参数,因为这个方法会自动将当前的Activity类名座位SharedPreferences的文件名。
向SharedPreferences文件存储数据
1.调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象。
2.向SharedPreferences.Editor对象中添加数据,添加字符串使用putString()方法,以此类推。
3.调用apply()方法将添加的数据提交。
新建SharedPreferencesTest项目
修改activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/saveButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save Date" />
</LinearLayout>
package com.example.sharedpreferencestest
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
saveButton.setOnClickListener {
val editor = getSharedPreferences("data", Context.MODE_PRIVATE).edit()
editor.putString("name", "Tom")
editor.putInt("age", 18)
editor.putBoolean("married", false)
editor.apply()
}
}
}
从SharedPreferences中读取数据
SharedPreferences对象提供了一系列的get方法:
参数:1.键; 2.默认值:表示当传入的键找不到对应的值时会以什么样的默认值进行返回。
例子:
修改activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/saveButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save Date" />
<Button
android:id="@+id/restoreButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Restore Data" />
</LinearLayout>
package com.example.sharedpreferencestest
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
saveButton.setOnClickListener {
val editor = getSharedPreferences("data", Context.MODE_PRIVATE).edit()
editor.putString("name", "Tom")
editor.putInt("age", 18)
editor.putBoolean("married", false)
editor.apply()
}
restoreButton.setOnClickListener {
val prefs = getSharedPreferences("data", Context.MODE_PRIVATE)
val name = prefs.getString("name", "")
val age = prefs.getInt("age", 0)
val married = prefs.getBoolean("married", false)
println("name is $name")
println("age is $age")
println("married is $married")
}
}
}
实现记住密码功能
打开BroadcastBestPractice项目,修改activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp" >
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="Account:" />
<EditText
android:id="@+id/accountEdit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="Password:" />
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/passwordEdit"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:inputType="textPassword" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/rememberPass"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="Remember password" />
</LinearLayout>
<Button
android:id="@+id/login"
android:layout_width="200dp"
android:layout_height="60dp"
android:layout_gravity="center_horizontal"
android:text="Login" />
</LinearLayout>
添加了一个新的控件Checkbox,这是一个复选框。
修改LoginActivity:
package com.example.broadcastbestpractice.ui.login
import android.app.Activity
import android.content.Context
import android.content.Intent
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import android.os.Bundle
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.Button
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.Toast
import com.example.broadcastbestpractice.BaseActivity
import com.example.broadcastbestpractice.MainActivity
import com.example.broadcastbestpractice.R
import kotlinx.android.synthetic.main.activity_login.*
class LoginActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
val login = findViewById<Button>(R.id.login)
val prefs = getPreferences(Context.MODE_PRIVATE)
val isRemember = prefs.getBoolean("remember_password", false)
if (isRemember) {
val account = prefs.getString("account", "")
val password = prefs.getString("password", "")
accountEdit.setText(account)
passwordEdit.setText(password)
rememberPass.isChecked = true
}
login.setOnClickListener {
val account = accountEdit.text.toString()
val password = passwordEdit.text.toString()
if (account == "admin" && password == "123456") {
val editor = prefs.edit()
if (rememberPass.isChecked) {
editor.putBoolean("remember_password", true)
editor.putString("account", account)
editor.putString("password", password)
} else {
editor.clear()
}
editor.apply()
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
} else {
Toast.makeText(this, "account or password is invalid", Toast.LENGTH_SHORT).show()
}
}
}
}