7. 持久化技术
7. 持久化技术
-
持久化技术可以让数据在瞬时状态和持久状态之间进行转换
- 文件存储
- SharedPreferences 存储
- 数据区存储
-
MainActivity2
-
package com.example.helloworld import android.content.Context import android.content.Intent import android.os.Bundle import android.util.Log import android.widget.ArrayAdapter import android.widget.Button import android.widget.ListView import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar class MainActivity2 : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.second_layout) // toolbar 部分 val toolbar: Toolbar = findViewById(R.id.toolbar2) setSupportActionBar(toolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) // 设置返回按钮 toolbar.setNavigationOnClickListener { finish() } // 设置结束 act2 ActivityCollector.addActivity(this) // 从前一个 Activity 接收数据 val extraData1 = intent.getStringExtra("param1") val extraData2 = intent.getStringExtra("param2") Log.d("Activity2", "param1 is $extraData1, param2 is $extraData2") // 返回数据(但是未实现) val button2: Button = findViewById(R.id.button2) // 通过 id 找到 view, 并指明类型为 button button2.setOnClickListener { val intent = Intent().apply { putExtra("data_return", "Hello Activity1") } setResult(RESULT_OK, intent) finish() } // 关闭所有 Activity val button3: Button = findViewById(R.id.button3) button3.setOnClickListener { ActivityCollector.finishAll() } val button4: Button = findViewById(R.id.button4) button4.setOnClickListener { startNewActivity(this, MainActivity3::class.java) } val button5: Button = findViewById(R.id.button5) button5.setOnClickListener { startNewActivity(this, MainActivity4::class.java) } val button7: Button = findViewById(R.id.button7) button7.setOnClickListener { startNewActivity(this, FragmentActivity::class.java) } val button8: Button = findViewById(R.id.button8) button8.setOnClickListener { startNewActivity(this, FileStorage::class.java) } val button9: Button = findViewById(R.id.button9) button9.setOnClickListener { startNewActivity(this, DataPreference::class.java) } val button10: Button = findViewById(R.id.button10) button10.setOnClickListener { startNewActivity(this, SqliteDB::class.java) } } }
-
-
second_layout
-
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar2" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" android:theme="?attr/actionBarTheme" /> <Button android:id="@+id/button2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Back" /> <Button android:id="@+id/button3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Quit App" /> <Button android:id="@+id/button4" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Go third" /> <Button android:id="@+id/button5" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Go forth" /> <Button android:id="@+id/button7" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Go Fragment" /> <Button android:id="@+id/button8" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="File Storage" /> <Button android:id="@+id/button9" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="SharedPreferences" /> <Button android:id="@+id/button10" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="SQLite" /> </LinearLayout>
-
1. 文件存储
-
FileStorage
-
package com.example.helloworld import android.content.Context import android.os.Bundle import android.widget.EditText import android.widget.Toast import java.io.BufferedReader import java.io.BufferedWriter import java.io.IOException import java.io.InputStreamReader import java.io.OutputStreamWriter class FileStorage : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 设置 layout setContentView(R.layout.file_storage_layout) ActivityCollector.addActivity(this) val editText : EditText = findViewById(R.id.editText) val inputText = load() // 启动时读取数据 if (inputText.isNotEmpty()) { editText.setText(inputText) editText.setSelection(inputText.length) Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show() } } override fun onDestroy() { // 退出程序时自动保存字符串 super.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() } } 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() } }
-
-
file_storage_layout
-
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Type something here" /> </LinearLayout>
-
2. SharedPreferences
-
DataPerference
-
package com.example.helloworld import android.content.Context import android.content.Intent import android.os.Bundle import android.widget.Button import android.widget.CheckBox import android.widget.EditText import android.widget.Toast import androidx.core.content.edit class DataPreference : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.data_perference) val prefs = getPreferences(Context.MODE_PRIVATE) val isRemember = prefs.getBoolean("remember_password", false) val accountEdit: EditText = findViewById(R.id.accountEdit) val passwordEdit: EditText = findViewById(R.id.passwordEdit) val rememberPass: CheckBox = findViewById(R.id.rememberPass) val login: Button = findViewById(R.id.login) 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() // 如果账号是admin且密码是123456,就认为登录成功 if (account == "admin" && password == "123456") { prefs.edit { if (rememberPass.isChecked) { // 检查复选框是否被选中 putBoolean("remember_password", true) putString("account", account) putString("password", password) } else { clear() } } val intent = Intent(this, MainActivity::class.java) startActivity(intent) finish() } else { Toast.makeText(this, "account or password is invalid", Toast.LENGTH_SHORT).show() } } } }
-
-
data_perference
-
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <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:id="@+id/passwordEdit" android:layout_width="0dp" android:layout_height="wrap_content" 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>
-
3. SQLite
-
SqliteDB.kt
-
package com.example.helloworld import android.content.ContentValues import android.content.Context import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper import android.os.Bundle import android.util.Log import android.widget.Button import android.widget.Toast class MyDatabaseHelper(val context: Context, name: String, 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 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) } 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") } } } class SqliteDB : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.sql_layout) ActivityCollector.addActivity(this) // 调用 helper 根据版本号创建或者升级数据库 val dbHelper = MyDatabaseHelper(this, "BookStore.db", 2) val createDatabase: Button = findViewById(R.id.createDatabase) createDatabase.setOnClickListener { dbHelper.writableDatabase } // 添加数据 val addData: Button = findViewById(R.id.addData) 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) // 插入第二条数据 } // 更新数据 val updateData: Button = findViewById(R.id.updateData) updateData.setOnClickListener { val db = dbHelper.writableDatabase val values = ContentValues() values.put("price", 10.99) db.update("Book", values, "name = ?", arrayOf("The Da Vinci Code")) } // 删除数据 val deleteData: Button = findViewById(R.id.deleteData) deleteData.setOnClickListener { val db = dbHelper.writableDatabase db.delete("Book", "pages > ?", arrayOf("500")) } // 查询数据 val queryData: Button = findViewById(R.id.queryData) 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("SqliteDB", "book name is $name") Log.d("SqliteDB", "book author is $author") Log.d("SqliteDB", "book pages is $pages") Log.d("SqliteDB", "book price is $price") } while (cursor.moveToNext()) } cursor.close() } // 使用事务确保原子性进行数据替换 val replaceData: Button = findViewById(R.id.replaceData) replaceData.setOnClickListener { val db = dbHelper.writableDatabase db.beginTransaction() // 开启事务 try { db.delete("Book", null, null) if (true) { // 手动抛出一个异常,让事务失败 throw NullPointerException() } val values = ContentValues().apply { put("name", "Game of Thrones") put("author", "George Martin") put("pages", 720) put("price", 20.85) } db.insert("Book", null, values) db.setTransactionSuccessful() // 事务已经执行成功 } catch (e: Exception) { e.printStackTrace() } finally { db.endTransaction() // 结束事务 } } } }
-
-
sql_layout
-
<?xml version="1.0" encoding="utf-8"?> <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>
-
// 添加数据
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",
arrayOf("The Da Vinci Code", "Dan Brown", "454", "16.96")
)
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",
arrayOf("The Lost Symbol", "Dan Brown", "510", "19.95")
)
// 更新数据
db.execSQL("update Book set price = ? where name = ?", arrayOf("10.99", "The Da Vinci Code"))
// 删除数据
db.execSQL("delete from Book where pages > ?", arrayOf("500"))
// 查询数据
val cursor = db.rawQuery("select * from Book", null)

浙公网安备 33010602011771号