首页 > 解决方案 > 如何提高 Android 中的内容解析器查询速度?

问题描述

我想显示包含图像/视频的文件夹列表。另外,我想获取该文件夹中图像/视频的数量,最近的图像/视频。我还想在列表顶部显示相机、所有媒体和所有视频文件夹,如 WhatsApp。

fun getImageBuckets(mContext: Context) {
    viewModelScope.launch(Dispatchers.IO) {
        imageFolderList.clear()
        val uri = MediaStore.Files.getContentUri("external")
        val projection = arrayOf(
            MediaStore.Files.FileColumns._ID,
            MediaStore.Files.FileColumns.BUCKET_DISPLAY_NAME,
            MediaStore.Files.FileColumns.DATA,
            MediaStore.Files.FileColumns.MIME_TYPE
        )
        // Return only video and image metadata.
        val selection = (MediaStore.Files.FileColumns.MEDIA_TYPE + "="
                + MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
                + " OR "
                + MediaStore.Files.FileColumns.MEDIA_TYPE + "="
                + MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
        val order = MediaStore.Files.FileColumns.DATE_ADDED
        val cursor: Cursor? =
            mContext.contentResolver.query(uri, projection, selection, null, order)
        var path = ""
        var id: Long
        var bucketPath: String? = null
        var bucketCompletePath: String
        var bucketCameraPath = ""
        var mimeType: String
        var imageDetail: ImageDetail
        val cameraPathName =
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
                .toString() + "/Camera"

        val folderMap: MutableMap<String, FolderDetail> = mutableMapOf()
        val allMedias: MutableList<ImageDetail> = mutableListOf()
        val allVideos: MutableList<ImageDetail> = mutableListOf()

        if (cursor != null) {
            val allMedia = FolderDetail("All media", path, 0, MediaFolderType.ALL_MEDIA)
            val allVideo = FolderDetail("All videos", path, 0, MediaFolderType.ALL_VIDEO)

            if (cursor.moveToLast()) {
                do {
                    id = cursor.getLong(0)
                    bucketPath = cursor.getString(1)
                    path = cursor.getString(2)
                    mimeType = cursor.getString(3)
                    // val file = ImagePickerUtils.makeSafeFile(path) ?: continue
                    if (bucketPath == null) {
                        val parent = File(path).parentFile
                        bucketPath = if (parent != null) {
                            parent.name
                        } else {
                            PickerConstants.EMPTY_STRING
                        }
                    }

                    imageDetail = ImageDetail(id, path)
                    allMedias.add(imageDetail)

                    if (bucketPath != null) {
                        bucketCompletePath = path.substringBeforeLast("/")
                        var folder = folderMap[bucketCompletePath]
                        if (folder == null) {
                            if (path.contains(cameraPathName, true)) {
                                bucketCameraPath = bucketCompletePath
                                folder =
                                    FolderDetail(bucketPath, path, 0, MediaFolderType.CAMERA)
                                folderMap[bucketCompletePath] = folder
                            } else {
                                folder =
                                    FolderDetail(bucketPath, path, 0, MediaFolderType.FOLDER)
                                folderMap[bucketCompletePath] = folder
                            }
                        }
                        folder.images.add(imageDetail)

                        if (mimeType.contains("video", true)) {
                            allVideos.add(imageDetail)
                        }
                    }
                } while (cursor.moveToPrevious())
                cursor.close()
                if (allMedias.isNotEmpty()) { // Check and Add top 3 folders has data then add at top
                    allMedia.images.addAll(allMedias)
                    allMedia.firstImagePath = allMedias[0].path
                    imageFolderList.add(allMedia)
                    if (allVideos.isNotEmpty()) {
                        allVideo.images.addAll(allVideos)
                        allVideo.firstImagePath = allVideos[0].path
                        imageFolderList.add(allVideo)
                    }
                    if (bucketCameraPath.isNotBlank()) {
                        val cameraMedia = folderMap[bucketCameraPath]
                        folderMap.remove(bucketCameraPath)
                        imageFolderList.add(0, cameraMedia!!)
                    }
                }
                imageFolderList.addAll(folderMap.values)
            }
        }
        getFolderListDiffResult()
    }
}

这是用于实现此目的的代码,读取 9000 个媒体文件需要 200 毫秒。我想进一步提高逻辑性能。上述代码的任何性能输入?

标签: androidperformancecursorstorageandroid-contentresolver

解决方案


推荐阅读