如何存储registerForActivityResult返回的图片URI解决配置变更图片消失问题
问题根因
你遇到的报错是lateinit变量的特性导致的:lateinit修饰的变量必须在访问前完成初始化,如果你还没有从相册选择过图片,imageUri没有被赋值,系统调用onSaveInstanceState时访问该变量就会触发未初始化异常。
具体解决步骤
步骤1:修改全局变量声明(推荐方案)
放弃使用lateinit,改为可空类型并设置默认值为null,从根源避免未初始化问题:
private var imageUri: Uri? = null
步骤2:在相册选择回调中给全局变量赋值
你之前的回调只给ImageView设置了Uri,没有给全局变量赋值,补充这行逻辑:
val selectImageFromGalleryResult = registerForActivityResult( ActivityResultContracts.GetContent()) { uri: Uri? -> uri?.let { imageUri = it // 新增这行,给全局变量赋值 profileImage.setImageURI(it) } } selectBtn.setOnClickListener { profileImage.visibility = View.VISIBLE selectImageFromGalleryResult.launch("image/*") }
步骤3:在onSaveInstanceState中存储Uri
Uri可以直接转成String格式存入Bundle:
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) // 仅当Uri不为空时存入,空值不需要处理 imageUri?.let { outState.putString("KEY_IMAGE_URI", it.toString()) } }
步骤4:在页面重建时恢复Uri
在onCreate中读取已存储的Uri,恢复图片展示:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 其他初始化逻辑... // 恢复保存的图片Uri if (savedInstanceState != null) { val savedUriStr = savedInstanceState.getString("KEY_IMAGE_URI") if (!savedUriStr.isNullOrEmpty()) { imageUri = Uri.parse(savedUriStr) profileImage.visibility = View.VISIBLE profileImage.setImageURI(imageUri) } } }
可选方案:坚持使用lateinit的处理方式
如果你不想修改lateinit的变量声明,可以在存储前先判断变量是否完成初始化,避免访问未初始化的变量:
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) if (::imageUri.isInitialized) { outState.putString("KEY_IMAGE_URI", imageUri.toString()) } }
该方案不如可空类型直观,更推荐使用上文的可空类型实现。
注:通过
ActivityResultContracts.GetContent获取的Uri会携带系统授予的临时访问权限,配置变更(如屏幕旋转)后权限仍然有效,不需要额外申请持久化权限。
内容的提问来源于stack exchange,提问作者Shubham Kumar
相关产品推荐
相关产品推荐

