打开相机按返回键出现ResultInfo结果传递失败异常求助
这个坑我之前踩过!当你在相机界面按返回键时,系统会返回result=0(也就是RESULT_CANCELED),而且返回的data是null,但你的代码里大概率把处理返回结果的参数声明成了非空类型,Kotlin的空校验机制直接就抛出异常了。咱们一步步解决:
先明确异常根源
你看到的java.lang.IllegalArgumentException: Parameter specified as non-null is null,就是Kotlin的Intrinsics.checkNotNull方法在检查时发现,你声明为非空的参数(比如Intent)实际传入了null,直接触发了崩溃。
解决方案分两种场景
场景1:使用传统的onActivityResult方法
如果你的代码还是用旧的onActivityResult处理相机返回,之前的错误写法可能是这样的:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == 1888) { // 尝试处理相机返回结果 } }
这里的data被声明为非空的Intent,但返回取消时data是null,直接触发异常。改成可空类型+空判断即可:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == 1888) { if (resultCode == Activity.RESULT_OK) { // 只有结果成功时才处理data,此时data大概率非空 data?.let { intent -> // 你的业务逻辑:比如获取图片Uri val imageUri = intent.data // ... } } else { // 处理用户取消拍照的情况,比如提示或重置状态 Toast.makeText(this, "你取消了拍照", Toast.LENGTH_SHORT).show() } } }
场景2:使用Jetpack Activity Result API(推荐)
现在官方推荐用registerForActivityResult来处理返回结果,如果你之前的回调里把参数声明成了非空,比如:
// 错误示例:PickVisualMedia的回调参数声明为非空Uri val pickImageLauncher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri: Uri -> // 用户取消时uri为null,直接崩溃 }
或者用StartActivityForResult时直接断言data非空:
// 错误示例:用!!断言非空,取消时会炸 val cameraLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { val data = result.data!! // ... } }
正确的写法是把参数改成可空类型,并且做空判断:
// 示例1:PickVisualMedia的正确处理 val pickImageLauncher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri: Uri? -> uri?.let { // 处理选中的图片Uri } ?: run { // 用户取消了操作,做对应处理 Toast.makeText(this, "取消选择图片", Toast.LENGTH_SHORT).show() } } // 示例2:StartActivityForResult的正确处理 val cameraLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { result.data?.let { intent -> // 处理相机返回的data } } else { // 处理取消逻辑 } }
核心总结
Kotlin的非空校验是编译+运行时双重检查,只要你声明了非空参数,就必须保证它不会为null。在处理系统返回的结果时,一定要考虑到用户取消操作的场景(此时data大概率为null),把对应的参数改成可空类型(加?),并在使用前做空安全处理(比如let、?:或者if (data != null))。
内容的提问来源于stack exchange,提问作者unpitted.com

