一、文件存储:
将数据存储到文件:
Context类中提供了一个openFileOutput()方法,可以用于将数据存储到指定的文件中。
该方法接受两个参数:
第一个参数是文件名,文件创建时使用,不可以包含路径,只是文件名,因为所有的文件都默认存于 /data/data/<package name>/files 目录下。
第二个参数是文件的操作模式:主要有MODE_PRIVATE 和 MODE_APPEND两种,默认是MODE_PRIVATE,表示,当存在相同名称的文件时,所写入的内容会自动覆盖原有文件中的内容。
MODE_APPEND,表示,如果该文件已存在,会将所写入的内容追加到文件中,不存在的话就创建新的文件。
openFileOutput() 返回的是一个FileOutputStream对象,得到对象之后,可以通过java流的方式,写入文件中。以下是代码示例,展示如何将一段文本工作内容保存到文件中:
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()
}
}
这里通过openFileOutput()方法能够得到一个FileOutputStream对象,然后借助对象构建一个OutputStreamWriter对象,接着使用OutputStreamWriter对象创建出一个BufferedWriter对象,然后就可以通过BufferedWriter对象写入文件了。
use 函数是Kotlin的一个内置扩展函数,他会保证 Lambda 中的代码全部执行完之后自动将外层的流关闭,这样就不需要手动写一个finally语句去手动关闭流了!!!
写一个示例,将EditText控件中的文本内容保存下来,代码如下:
需要在布局文件中先添加一个EditText控件,然后再MainActivity中修改代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onDestroy() {
super.onDestroy()
Log.d("MainActivity","onDestroy")
val editText: EditText = findViewById(R.id.editText)
val inputText = editText.text.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()
}
}
}
重写onDestory() 方法,保证Activity在销毁时,能够将文本内容保存到文件中。保存的文件可以从右下角的Device File Explorer中的 /data/data/<package name>/files目录中找到名为data的文件。
从文件中读取数据:
类似于将数据存储到文件中,Context类中还提供了一个openFileInput()方法,用于从文件中读取数据。这个方法要比openFileOutput()简单一些,它只接收一个参数,即要读取的文件名,然后系统会自动到 /data/data/<package name>/files 中加载这个文件,并返回一个 FileInputStream 对象,得到这个对象,会通过流的方式将数据读取出来。
示例代码如下:
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()
}
先通过openFileInput() 获取一个 FileInputStream 对象,然后通过它构建出一个 InputStreamReader 对象,然后再根据这个对象构建出一个 BufferedReader 对象,这样就可以通过BufferedReader对象来逐行读取文本文件中的内容,并拼接到StringBuilder() 对象中,然后返回内容。
二、SharedPreferences存储
不同于文件的存储方式,SharedPreferences是使用键值对的方式来存储数据的。也就是说,当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且SharedPreferences还支持多种不同的数据类型存储,如果存储的数据类型是整型,那么读取出来的数据也是整型的;如果存储的数据是一个字符串,那么读取出来的数据仍然是字符串。
将数据存储到SharedPreferences中
首先、要向SharedPreferences 中存储数据,需要先获取一个SharedPreferences对象。获取的方法有两种:
1、Context类的 getSharedPreferences() 方法:接受两个参数
第一个参数是用于指定 SharedPreferences 的名称,没有则创建一个,保存在 /data/data/<packagename>/shared_prefs/ 目录下。
第二个参数用于指定操作模式,目前只有默认的 MODE_PRIVATE模式,相当于传入0.
2、Activity类的 getSharedPreferences() 方法:它只接受一个参数,因为会默认将Activity的类名作为文件名。
获取了对象,可以向对象中存储数据,主要分3部分实现:
(1) 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象。
(2) 向SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用putBoolean()方法,添加一个字符串则使用putString()方法,以此类推。
(3) 调用apply()方法将添加的数据提交,从而完成数据存储操作。
示例代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val saveButton: Button = findViewById(R.id.saveButton)
saveButton.setOnClickListener {
val editor = getSharedPreferences("data", Context.MODE_PRIVATE).edit()
editor.putString("name", "Tom")
editor.putInt("age", 25)
editor.putBoolean("married", false)
editor.apply()
}
}
}
为按钮注册点击事件,进行数据保存。打开Device File Explorer,进入/data/data/<packagename>/shared_prefs/ 可看到:
SharedPreferences文件是使用XML格式来对数据进行管理的。打开data.xml 内容如下:
<map>
<string name="name">Tom</string>
<boolean name="married" value="false" />
<int name="age" value="25" />
</map>
SharedPreferences是通过map数据结构保存数据的。
从SharedPreferences中读取数据:
SharedPreferences对象中提供了一系列的get方法,用于读取存储的数据,每种get方法都对应了
SharedPreferences.Editor中的一种put方法,比如读取一个布尔型数据就使用getBoolean()方法,读取一个字符串就使用getString()方法。
这些get方法都接收两个参数:
第一个参数是键,传入存储数据时使用的键就可以得到相应的值了;
第二个参数是默认值,即表示当传入的键找不到对应的值时会以什么样的默认值进行返回。
我们在还原数据按钮的点击事件中首先通过getSharedPreferences()方法得到了SharedPreferences对象。然后分别调用该对象的getString()、getInt()和getBoolean()等方法,如果未获取到,则用传入的默认值代替,示例如下:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val saveButton: Button = findViewById(R.id.saveButton)
val restoreButton: Button = findViewById(R.id.restoreButton)
......
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)
Log.d("MainActivity", "name is $name")
Log.d("MainActivity", "age is $age")
Log.d("MainActivity", "married is $married")
}
}
}
用这个可以实现简单的记住密码功能!!!!