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) 

posted @ 2026-01-14 17:42  y丶innocence  阅读(4)  评论(0)    收藏  举报