点击setOnClickListener绑定的保存按钮后应用崩溃的原因排查
问题分析:Firebase数据上传后应用崩溃
我通过Firebase实现表单提交+封面图上传功能,填写表单并选择图片后,点击绑定了setOnClickListener的「保存」按钮,按钮负责将所有信息和图片上传至Firebase,之后返回主页面。但主页面显示前应用崩溃,抛出如下错误:
2022-08-16 20:49:53.847 21445-21445/com.example.gesit E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.gesit, PID: 21445 java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.material.button.MaterialButton.setEnabled(boolean)' on a null object reference at com.example.gesit.TambahProduk.saveProductInformation$lambda-6(TambahProduk.kt:313) at com.example.gesit.TambahProduk.$r8$lambda$WSqVgd-3d_M5F9vVqHMPnqwiv5o(Unknown Source:0) at com.example.gesit.TambahProduk$$ExternalSyntheticLambda3.onComplete(Unknown Source:2) at com.google.android.gms.tasks.zzi.run(com.google.android.gms:play-services-tasks@@18.0.1:1) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8751) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
上传数据和图片的核心代码如下:
private fun saveProductInformation(downloadedUrl: String) { auth = FirebaseAuth.getInstance() val uid = auth.currentUser?.uid.toString() databaseReference = FirebaseDatabase.getInstance() .getReference("User") val productName = productName.text.toString() val productInfo = DataProduk(productName, uid) if (uid != null) { databaseReference.child(uid).setValue(productInformation) .addOnCompleteListener { saveButton.isEnabled = false Toast.makeText(this@AddProduct,"Product added",Toast.LENGTH_SHORT).show() hideProgressBar() } } }
崩溃原因
错误日志明确指向空指针异常:在调用saveButton.setEnabled(false)时,saveButton对象已变为null。
最可能的触发场景:
你上传数据后,可能提前执行了返回主页面的逻辑(比如调用finish()),导致当前Activity被销毁,视图资源被回收。而Firebase的addOnCompleteListener是异步回调,当回调执行时,saveButton对应的视图已经不存在,引用变为null,调用其方法就会引发崩溃。
另外代码还存在两个隐性问题:
- 变量名不一致:创建的实体是
productInfo,但上传时传入的是productInformation,会导致运行错误。 uid通过toString()获取,即使currentUser为null,uid也会是字符串"null",后续if (uid != null)的判断完全失效。
修复建议
- 在异步回调中先判断Activity状态,再操作UI:
databaseReference.child(uid).setValue(productInfo) .addOnCompleteListener { task -> // 确保Activity未被销毁再操作UI if (!isFinishing && !isDestroyed) { saveButton?.isEnabled = false Toast.makeText(this@TambahProduk,"Product added",Toast.LENGTH_SHORT).show() hideProgressBar() // 延迟执行页面跳转,确保UI操作完成 Handler(Looper.getMainLooper()).postDelayed({ finish() }, 1000) } }
- 修正变量名错误,将
productInformation改为productInfo。 - 优化用户登录状态判断:
val uid = auth.currentUser?.uid ?: return // 用户未登录时直接终止方法执行
内容的提问来源于stack exchange,提问作者Tommy -
相关产品推荐
相关产品推荐

