惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
I
Intezer
人人都是产品经理
人人都是产品经理
F
Full Disclosure
A
About on SuperTechFans
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
J
Java Code Geeks
博客园 - 三生石上(FineUI控件)
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
云风的 BLOG
云风的 BLOG
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
博客园 - 司徒正美
P
Proofpoint News Feed
宝玉的分享
宝玉的分享
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
The GitHub Blog
The GitHub Blog
L
LangChain Blog
Last Week in AI
Last Week in AI
B
Blog
Project Zero
Project Zero
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Schneier on Security
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
U
Unit 42
B
Blog RSS Feed
Y
Y Combinator Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Privacy International News Feed
N
News and Events Feed by Topic
W
WeLiveSecurity
Cloudbric
Cloudbric
G
GRAHAM CLULEY
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
Check Point Blog
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Latest news
Latest news
S
Secure Thoughts
Simon Willison's Weblog
Simon Willison's Weblog
Scott Helme
Scott Helme
H
Heimdal Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog

博客园 - y丶innocence

临时111 RecyclerView 数据多时无法滑动:ConstraintLayout 约束高度修复笔记 Android Kotlin OkHttp3 WebSocket 长连接与 Gson 数据解析系统笔记 Android + Kotlin + OkHttp WebSocket 相关概念与使用流程笔记(TLS/证书 + 鉴权/会话) AI对话导出markdown格式流程 代理转发 分享文件 面向全球的app的excel导出和kotlin IO原理 安卓导出笔记(未整理) java&kotlin listener 0.7 动画 0.4 View 工作流程 0.3 view 滑动冲突 13. Jetpack 0. 安卓开发艺术探索参考资料 12. Material Design 5. Fragment java 基础 4. UI 开发 3. Activity 2.2 Kotlin 面向对象 2.3 Kotlin高级 2.1 Kotlin基础 1. Android简介 [OpenJudge] 反正切函数的应用 (枚举)(数学) [OpenJudge] 摘花生 (模拟)
7. 持久化技术
y丶innocence · 2026-01-14 · via 博客园 - y丶innocence

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>
      
  • 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)