You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保存Activity状态?实现APP关闭/重启后保留图片及文本数据

需求与现有代码

我需要我的日记类APP能够保存图片状态与后续要添加的文本字段数据,使得用户关闭APP甚至重启手机后,数据仍能保留。

现有Activity代码如下:

class stageOne1 : AppCompatActivity() {

private lateinit var manifestImage: ImageView
companion object {
    const val IMAGE_REQUEST_CODE = 100
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_stage_one1)

    manifestImage = findViewById(R.id.manifestImage)
    manifestImage.setOnClickListener{
        pickImageGallery()
    }
}

private fun pickImageGallery(){
    val intent = Intent(Intent.ACTION_PICK)
    intent.type = "image/*"
    startActivityForResult(intent, IMAGE_REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?){
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == IMAGE_REQUEST_CODE && resultCode == RESULT_OK){
        manifestImage.setImageURI(data?.data)
    }
}

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
}

override fun onRestoreInstanceState(
    savedInstanceState: Bundle?,
    persistentState: PersistableBundle?
) {
    super.onRestoreInstanceState(savedInstanceState, persistentState)
}
持久化实现方案

一、图片持久化处理

从相册选择的图片URI是临时授权,重启手机后会失效,必须将图片复制到APP私有存储目录,保存本地文件路径:

  1. 添加图片复制工具方法
private fun saveImageToLocal(uri: Uri): String? {
    return try {
        val inputStream = contentResolver.openInputStream(uri)
        val fileName = "diary_image_${System.currentTimeMillis()}.jpg"
        val outputDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
        val outputFile = File(outputDir, fileName)
        val outputStream = FileOutputStream(outputFile)
        inputStream?.copyTo(outputStream)
        inputStream?.close()
        outputStream.close()
        outputFile.absolutePath
    } catch (e: IOException) {
        e.printStackTrace()
        null
    }
}
  1. 修改onActivityResult保存图片路径
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?){
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == IMAGE_REQUEST_CODE && resultCode == RESULT_OK){
        data?.data?.let { uri ->
            val imagePath = saveImageToLocal(uri)
            imagePath?.let {
                // 后续结合数据库保存路径
                manifestImage.setImageURI(Uri.fromFile(File(it)))
            }
        }
    }
}

二、文本与图片路径的持久化(推荐Room数据库)

日记类应用需要存储结构化的多条目数据,Room是官方推荐的本地数据库方案,比SharedPreferences更适合:

  1. 添加Room依赖(Module级build.gradle)
dependencies {
    def room_version = "2.6.1"
    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
    implementation "androidx.room:room-ktx:$room_version"
}
  1. 定义日记实体类
@Entity(tableName = "diaries")
data class Diary(
    @PrimaryKey(autoGenerate = true) val id: Int = 0,
    val content: String, // 日记文本内容
    val imagePath: String?, // 图片本地路径
    val createTime: Long = System.currentTimeMillis()
)
  1. 创建DAO接口
@Dao
interface DiaryDao {
    @Insert
    suspend fun insertDiary(diary: Diary)

    @Query("SELECT * FROM diaries ORDER BY createTime DESC")
    suspend fun getAllDiaries(): List<Diary>

    @Update
    suspend fun updateDiary(diary: Diary)
}
  1. 创建Room数据库类
@Database(entities = [Diary::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun diaryDao(): DiaryDao

    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null

        fun getDatabase(context: Context): AppDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "diary_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}
  1. 在Activity中集成Room
private lateinit var db: AppDatabase
private lateinit var diaryDao: DiaryDao

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_stage_one1)
    
    // 初始化数据库
    db = AppDatabase.getDatabase(this)
    diaryDao = db.diaryDao()
    
    manifestImage = findViewById(R.id.manifestImage)
    manifestImage.setOnClickListener{ pickImageGallery() }

    // 读取已保存的最新日记,恢复数据
    lifecycleScope.launch {
        val latestDiary = diaryDao.getAllDiaries().firstOrNull()
        latestDiary?.let {
            // 恢复图片
            it.imagePath?.let { path ->
                manifestImage.setImageURI(Uri.fromFile(File(path)))
            }
            // 恢复文本(假设你有一个EditText控件)
            // contentEditText.setText(it.content)
        }
    }
}

// 保存日记的方法(比如用户点击保存按钮时调用)
private fun saveCurrentDiary(content: String, imagePath: String?) {
    lifecycleScope.launch {
        val diary = Diary(content = content, imagePath = imagePath)
        diaryDao.insertDiary(diary)
    }
}

三、临时状态保存(可选)

如果需要处理APP后台被杀但未重启手机的场景,可以完善onSaveInstanceState临时保存状态,但这不能替代数据库的持久化:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    // 假设你有存储当前图片路径的变量
    val currentImagePath = getCurrentImagePath() // 需自行实现获取当前路径的逻辑
    outState.putString("TEMP_IMAGE_PATH", currentImagePath)
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    val tempImagePath = savedInstanceState.getString("TEMP_IMAGE_PATH")
    tempImagePath?.let {
        manifestImage.setImageURI(Uri.fromFile(File(it)))
    }
}

内容的提问来源于stack exchange,提问作者Samuel Okunato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:35:36