繁体   English   中英

为什么我在尝试将图像分配给我的 GridView 时收到此 NullPointerException?

[英]Why am I getting this NullPointerException while trying to assign images to my GridView?

我有一个 GridView 应用与 object 实例相关的不同图像。 我正在使用 RealPathUtil object 来处理文件路径的检索以解码和显示位图。

当我打开将这些图像分配给网格的活动时,我的应用程序会自动崩溃并显示一个 NullPointerException,指向声明此 if 子句的行:

else if ("content".equals(uri.scheme!!, ignoreCase = true)) {
       // Return the remote address
       return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(context, uri, null, null)
}

我熟悉 NullPointerExceptions 以及它们通常被抛出的原因,但我真的不明白为什么会给出这个。 由于我将图像显示方法从 URI 切换到 Bitmap,因此我尝试分配的图像都没有正确显示。 当我使用 URI 将图像分配给 ImageViews 时,没有出现这个问题,但我不得不切换,因为这会在其他设备上产生问题。

这是处理 GridView 的适配器的代码,它导致出现此错误。 从 tempUri 的值设置到末尾时发生错误:

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val view: View = View.inflate(activity,R.layout.layout_adapter,null)

        // Get view data from UI elements - image, name, and count
        val tv_lang = view.findViewById(R.id.itemName) as TextView
        val imageView = view.findViewById<ImageView>(R.id.itemImage)
        val itemCount = view.findViewById(R.id.itemCount) as TextView

        // Assign data to UI elements
        tv_lang.text = itemList[position].itemNote
        itemCount.text = itemList[position].itemCount.toString()
        val itemImage = itemList[position].itemImage


        // Assign each item image to corresponding grid ImageView
        tempUri = Uri.parse(itemImage)
        realPathUri = RealPathUtil.getRealPath(parent!!.context, tempUri).toString()
        val myBitmap = BitmapFactory.decodeFile(realPathUri)
        imageView.setImageBitmap(myBitmap)

        return view
}

RealPathUtil

    object RealPathUtil {
        // SDK <= 11 && SDK < 19
        /* Calls either getRealPathFromURIAPI11to19 or getRealPathFromURIAPI19, depending upon which API the software detects the user running the app through. */
        @SuppressLint("ObsoleteSdkInt")
        fun getRealPath(context: Context, fileUri: Uri): String? {
            return if (Build.VERSION.SDK_INT < 19) {
                getRealPathFromURIAPI11to18(context, fileUri)
            } else {
                getRealPathFromURIAPI19(context, fileUri)
            }
        }

        /* Uses other methods within the RealPathUtil object to determine
        * location list file path based upon the user's phone's active API (11-18). */
        @SuppressLint("NewApi")
        fun getRealPathFromURIAPI11to18(context: Context, contentUri: Uri): String? {
            val project = arrayOf(MediaStore.Images.Media.DATA)
            var result: String? = ""

            val cursorLoader = CursorLoader(context, contentUri, project, null, null, null)
            val cursor = cursorLoader.loadInBackground()

            if (cursor != null) {
                val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
                cursor.moveToFirst()
                result = cursor.getString(columnIndex)
                cursor.close()
            }
            return result
        }

        /* Uses other methods within the RealPathUtil object to determine location list file
        path based upon the user's phone's active API (19). */
        @SuppressLint("NewApi")
        fun getRealPathFromURIAPI19(context: Context, uri: Uri): String? {
            val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

            // Create the DocumentProvider
            if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
                // Safe cast the ExternalStorageProvider
                if (isExternalStorageDocument(uri)) {
                    val docId = DocumentsContract.getDocumentId(uri)
                    val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                    val type = split[0]

                    if ("primary".equals(type, ignoreCase = true)) {
                        return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                    }
                } else if (isDownloadsDocument(uri)) {
                    var cursor: Cursor? = null

                    try {
                        cursor = context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.DISPLAY_NAME), null, null, null)
                        cursor!!.moveToNext()

                        val fileName = cursor.getString(0)
                        val path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName

                        if (!TextUtils.isEmpty(path)) {
                            return path
                        }
                    } finally {
                        cursor?.close()
                    }

                    val id = DocumentsContract.getDocumentId(uri)

                    if (id.startsWith("raw:")) {
                        return id.replaceFirst("raw:".toRegex(), "")
                    }
                    val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads"), java.lang.Long.valueOf(id))

                    return getDataColumn(context, contentUri, null, null)
                } else if (isMediaDocument(uri)) {
                    val docId = DocumentsContract.getDocumentId(uri)
                    val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                    val type = split[0]

                    var contentUri: Uri? = null

                    when (type) {
                        "image" -> contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                        "video" -> contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                        "audio" -> contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                    }

                    val selection = "_id=?"
                    val selectionArgs = arrayOf(split[1])

                    return getDataColumn(context, contentUri, selection, selectionArgs)
                } // Media Provider
                // Downloads Provider
            } else if ("content".equals(uri.scheme!!, ignoreCase = true)) {
                // Return the remote address
                return if (isGooglePhotosUri(uri))
                    uri.lastPathSegment
                else
                    getDataColumn(context, uri, null, null) /** Collapse this if-else block into one line if any new, unexplained I/O issues arise. */
            } else if ("file".equals(uri.scheme!!, ignoreCase = true)) {
                return uri.path
            } // File
            // MediaStore

            return null
        }

        private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
            var cursor: Cursor? = null
            val column = "_data"
            val projection = arrayOf(column)

            try {
                cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)

                if (cursor != null && cursor.moveToFirst()) {
                    val index = cursor.getColumnIndexOrThrow(column)
                    return cursor.getString(index)
                }
            } finally {
                cursor?.close()
            }
            return null
        }

        /* Takes the URI being analyzed and determines whether the URI authority is ExternalFileProvider or not. */
        private fun isExternalStorageDocument(uri: Uri): Boolean {
            return "com.android.externalstorage.documents" == uri.authority
        }

        /* Takes the URI being analyzed and determines whether the URI authority is DownloadsProvider or not. */
        private fun isDownloadsDocument(uri: Uri): Boolean {
            return "com.android.providers.downloads.documents" == uri.authority
        }

        /* Takes the URI being analyzed and determines whether the URI authority is MediaProvider or not. */
        private fun isMediaDocument(uri: Uri): Boolean {
            return "com.android.providers.media.documents" == uri.authority
        }

        /* Takes the URI being analyzed and determines whether the URI authority is Google Photos or not. */
        private fun isGooglePhotosUri(uri: Uri): Boolean {
            return "com.google.android.apps.photos.content" == uri.authority
        }
    }

我知道这与如何检索路径有关,但我真的不知道如何。 我已经使用这个 object 很长时间了,我从来没有遇到过这样的问题,所以我真的不知道从哪里开始调试。 我并不是要解决我的问题,但如果某个比我更有经验的精明人士可以告诉我这个问题来自哪里,我也许能够弄清楚。 再次感谢!

假设您所指的if子句是这个:

 else if ("content".equals(uri.scheme,!, ignoreCase = true)) {

NullPointerException 的明显位置是uri.scheme!! . 双键运算符用于断言具有可空类型的变量实际上不是null ,并检索其值。 当我们作为人类比编译器知道的更多时,这有时很有用......但人类也有可能是错误的!

如果uri.scheme是null,那么uri.scheme!! 将抛出 NullPointerException。

如何解决这个取决于你程序的 rest。 也许您不希望uri.scheme永远是 null,在这种情况下,您需要找出更深层次的根本原因。 但是,如果您确实希望uri.scheme有时可能是 null,您可以重写您的if条件:

else if (uri.scheme?.equals("content", ignoreCase = true) == true) {

使用 String.equals 时不需要检查 Null。 检查代码

public actual fun String?.equals(other: String?, ignoreCase: Boolean = false): Boolean { 
if (this === null) 
    return other === null
return if (!ignoreCase) (this as java.lang.String).equals(other) 
       else (this as java.lang.String).equalsIgnoreCase(other) 
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM