Android Kotlin 如何校验相册选图ImageView与EditText避免更新崩溃
问题根因
崩溃来自三个核心代码缺陷:
- 图片空校验逻辑存在严重问题:你同时判断了
imageView.equals(null)、imageView.visibility==null、imageView.drawable==null这类既冗余又容易触发异常的条件,且没有以自己持有的选图结果ImageUri作为唯一判断依据。当ImageView设置了默认占位图、或者视图状态异常时,空校验会直接失效,导致null值被传入Firebase上传逻辑触发崩溃;另外imageView.equals(null)的写法本身就存在空指针风险,当imageView实例为null时调用equals方法会直接崩溃。 - 输入框校验逻辑写反了:用
&&(逻辑与)判断「姓名和电话同时为空」才提示,会出现只填了其中一个字段就绕过校验往下执行的问题。 - 逻辑时序错误:数据库写入逻辑没有等待图片上传结果,不管图片上传成功还是失败都会执行,极易产生脏数据,且代码里存在冗余的重复toast提示。
修复方案
- 输入校验改为:姓名、电话任意一个为空就拦截提示,校验不通过直接终止流程。
- 图片校验只判断
ImageUri是否为null即可,删掉所有和ImageView状态相关的无效判断,校验不通过弹提示后直接终止流程。 - 把数据库写入逻辑挪到图片上传成功的回调内,保证只有头像上传成功后才更新用户信息,避免数据不一致。
- 删掉所有冗余、矛盾的逻辑(比如多余的未选图toast、无意义的
imageView.setEnabled(false))。
修复后可直接运行的代码
R.id.update_icon -> { email.setFocusable(false) name.setFocusable(false) phone.setFocusable(false) cameraIcon.visibility = View.GONE // 校验输入合法性 var inputValid = true if (TextUtils.isEmpty(name.text.toString())) { name.error = "Enter user name" inputValid = false } if (TextUtils.isEmpty(phone.text.toString())) { phone.error = "Enter Phone number" inputValid = false } if (!inputValid) return true // 校验是否选择头像 if (ImageUri == null) { Toast.makeText(this, "you have not choosed any profile picture", Toast.LENGTH_SHORT).show() return true } // 所有校验通过后执行上传逻辑 val formater = SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.getDefault()) val filename = formater.format(Date()) val storageRef = FirebaseStorage.getInstance().getReference("images/$filename") database = FirebaseDatabase.getInstance().getReference("Users") storageRef.putFile(ImageUri) .addOnSuccessListener { // 头像上传成功再更新用户数据到数据库 val userInfo = mapOf( "username" to name.text.toString(), "phoennumber" to phone.text.toString() ) database.child(name.text.toString()).updateChildren(userInfo) .addOnSuccessListener { imageView.setImageURI(null) Toast.makeText(applicationContext, "Successfully Updated", Toast.LENGTH_LONG).show() } .addOnFailureListener { Toast.makeText(applicationContext, "Update user info failed", Toast.LENGTH_LONG).show() } } .addOnFailureListener { Toast.makeText(this, "Image uploading failed", Toast.LENGTH_SHORT).show() } return true } else -> return onOptionsItemSelected(item)
额外注意点
- 永远不要依赖UI控件的状态作为业务数据的判断依据,比如判断是否选图要以自己从相册拿到后保存的
ImageUri为准,ImageView只是用来展示的控件,它的drawable、visibility状态随时可能被其他逻辑修改,作为判断依据极不可靠。 - 所有链式异步逻辑(比如先传图再写库)要把后续逻辑放到上一步的成功回调里,不要平铺写,不然会出现时序错乱。
- 做null校验的时候,永远不要在可能为null的对象上调用成员方法,比如
obj.equals(null)可以直接替换成obj == null,Kotlin本身有空安全特性,善用空安全操作符?.可以避免90%以上的空指针崩溃。
内容的提问来源于stack exchange,提问作者AndroidKotlin
相关产品推荐
相关产品推荐

