如何保存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私有存储目录,保存本地文件路径:
- 添加图片复制工具方法
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 } }
- 修改
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更适合:
- 添加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" }
- 定义日记实体类
@Entity(tableName = "diaries") data class Diary( @PrimaryKey(autoGenerate = true) val id: Int = 0, val content: String, // 日记文本内容 val imagePath: String?, // 图片本地路径 val createTime: Long = System.currentTimeMillis() )
- 创建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) }
- 创建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 } } } }
- 在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
相关产品推荐
相关产品推荐

