From 37f0c15cfc4746241a9d0c2c233d46a88a349fb4 Mon Sep 17 00:00:00 2001 From: ItzNotABug Date: Fri, 22 Nov 2024 15:25:16 +0530 Subject: [PATCH] fix: handle crash caused by deletion of file or directory associated with Uri. --- .../dfc/resolver/ResolverCompat.kt | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/dfc/src/main/java/com/lazygeniouz/dfc/resolver/ResolverCompat.kt b/dfc/src/main/java/com/lazygeniouz/dfc/resolver/ResolverCompat.kt index 6a25780..b5ff4dc 100644 --- a/dfc/src/main/java/com/lazygeniouz/dfc/resolver/ResolverCompat.kt +++ b/dfc/src/main/java/com/lazygeniouz/dfc/resolver/ResolverCompat.kt @@ -81,8 +81,11 @@ internal object ResolverCompat { */ internal fun count(context: Context, uri: Uri): Int { val childrenUri = createChildrenUri(uri) - getCursor(context, childrenUri, iconProjection)?.use { cursor -> return cursor.count } - return 0 + return getCursor( + context, + childrenUri, + iconProjection + )?.use { cursor -> return cursor.count } ?: 0 } /** @@ -108,6 +111,17 @@ internal object ResolverCompat { val listOfDocuments = arrayListOf() getCursor(context, childrenUri, fullProjection)?.use { cursor -> + val itemCount = cursor.count + /** + * Pre-sizing the list to avoid resizing overhead. + * This is especially beneficial for directories with a large number of files. + * + * Memory comparison for 8192 files: + * 1. With pre-sizing: 3.10 MB + * 2. Without pre-sizing: 9.60 MB + */ + if (itemCount > 10) listOfDocuments.ensureCapacity(itemCount) + while (cursor.moveToNext()) { val documentId: String = cursor.getString(0) val documentUri = DocumentsContract.buildDocumentUriUsingTree(uri, documentId) @@ -136,9 +150,20 @@ internal object ResolverCompat { * Get [Cursor] from [ContentResolver.query] with given [projection] on a given [uri]. */ fun getCursor(context: Context, uri: Uri, projection: Array): Cursor? { - return context.contentResolver.query( - uri, projection, null, null, null - ) + return try { + context.contentResolver.query( + uri, projection, null, null, null + ) + } catch (exception: Exception) { + /** + * This exception can occur in scenarios such as - + * + * - The Uri became invalid due to external changes (e.g., permissions revoked, storage unmounted, etc). + * - The file or directory represented by this Uri was probably deleted or became `inaccessible` after the Uri was obtained but before this operation was performed. + */ + ErrorLogger.logError("Exception while building the Cursor", exception) + null + } } // Make children uri for query.