图像存在,不为空,但我得到一个 NullPointerException

Image exists, not null, but I get an NullPointerException on it

简短介绍

我目前正在开发的应用程序从 JSON 获取图像,如果正确,它会使用它并在下次使用时将其保存为加载图像。

问题

突然间,应用程序开始在加载时崩溃,在进一步检查时,file.isFile && file.canRead() 我进行的 returns 检查是肯定的,但它仍然在 BitmapFactory.decodeStream 时崩溃。 该文件的字节数为 8k,与我使用的其他设备相比,同一张图像实际上有 43k 字节。

图像 json 是更大的 json 消息(大约 500kb)的一部分,它不在开头或结尾。发生这种情况之前的最后一次使用没有加载问题或标志显示下载可能已停止一半。即便如此,图像仍然有 8kb 所以我想它应该用它的部分创建一些东西而不是抛出 NullPointerException

我正在使用 Android Studio 3.0 Beta 4 并且代码在 Kotlin 中。我必须在这个设备上 运行 它 100 次,即使在这发生之后它 运行 在其他测试设备上也完全没问题,加上 iOS 应用程序完全相同 json 启动时

我在找什么

关于如何处理问题的建议,或者它是否是 Android 或 Kotlin 中的已知错误的信息。我可能可以在设备上重新安装该应用程序,它会再次正常,但我不希望在应用程序发布后发生这种情况,如果我能阻止的话。

LaterEdit: 在 Xaviers 的建议下,我已经将文件复制到桌面上,它肯定是格式错误的,当它加载时它实际上显示了一些严重格式错误的图像 运行宁 Mac。我试图上传它,但它只显示为空白的白色图像。它仍然有 8kb,所以它包含一些数据。 这怎么可能,可以预防吗?

代码

加载应用程序,我检查图像是否存在并将其加载到 imageView

try {
     if (DesignSupport().imageExists("logo", this)) {
         if (DesignSupport().loadImage("logo", this) != null) {
             imageView.setImageBitmap(DesignSupport().loadImage("logo", this))
         }
     }
 } catch (error: Error) {
     Log.i(tag, error.stackTrace.toString())
 }

检查图片是否存在

fun imageExists(string: String, context: Context) : Boolean {
        val path = android.os.Environment.getExternalStorageDirectory().toString() + "/" + context.applicationInfo.name + "/" + string + ".png"
        val file = File(path)
        return (file.isFile && file.canRead())
    }

加载图像

    fun loadImage(string: String, context: Context) : Bitmap {
            val path = android.os.Environment.getExternalStorageDirectory().toString() + "/" + context.applicationInfo.name + "/" + string + ".png"
            val fis = FileInputStream(path)
// it crashes at the next line, but when I print fis.available() it returns 8200
            return BitmapFactory.decodeStream(fis)
        }

崩溃日志

 java.lang.RuntimeException: Unable to start activity ComponentInfo{.GeneralAccessScreens.startupScreen}: java.lang.IllegalStateException: BitmapFactory.decodeStream(fis) must not be null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2412)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2470)
at android.app.ActivityThread.access0(ActivityThread.java:174)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5593)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: BitmapFactory.decodeStream(fis) must not be null
at SupportMethods.DesignSupport.loadImage(DesignSupport.kt:45)
at .GeneralAccessScreens.startupScreen.onCreate(startupScreen.kt:34)
at android.app.Activity.performCreate(Activity.java:5458)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)

导入报表

import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Base64
import android.util.Log
import android.view.inputmethod.InputMethodManager
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream

您确定崩溃是在同一个 loadImage() 方法中而不是在另一个方法中吗?在错误日志中,它说崩溃发生在 BitmapFactory.decodeReso…ystem(), R.drawable.logo),这似乎是另一个崩溃。

此外,您是否尝试过先进行重建?我在 AS 3.0 测试版中看到很多问题都通过这样做得到了解决。

documentation 开始,即使 fis 为 null 它也不应该因此错误而崩溃,只是 return 一个 null(重点是我的)。

Decode an input stream into a bitmap. If the input stream is null, or cannot be used to decode a bitmap, the function returns null. The stream's position will be where ever it was after the encoded data was read.

只是为了丢弃东西,你可以为 BitmapFactory 添加 import 语句吗?应该是 import android.graphics.BitmapFactory.

抛出特定异常是因为BitmapFactory.decodeStream(fis) returns null 而函数被指定为return 一个不可为空的对象。要么使 return 值可以为空,要么定义一个适当的替换,如果它 return null.

在后台 Kotlin 生成以下 "java" 代码:

Bitmap tmp = BitmapFactory.decodeStream(fis);
Intrinsics.checkExpressionValueIsNotNull(tmp, "BitmapFactory.decodeStream(fis)");
return tmp;

异常的来源是 Intrinsics.checkExpressionValueIsNotNull 调用。