Skip to content

Commit 6cc74ea

Browse files
committed
Remove recursive image counting - single SAF query per directory, cancel stale loads on navigation
1 parent 7f3fc44 commit 6cc74ea

3 files changed

Lines changed: 17 additions & 53 deletions

File tree

app/src/main/java/com/degard/imagecompressor/GalleryAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class GalleryAdapter(
6767
inner class FolderVH(private val b: GalleryFolderItemBinding) : RecyclerView.ViewHolder(b.root) {
6868
fun bind(folder: FolderEntry) {
6969
b.tvFolderName.text = folder.name
70-
b.tvFolderCount.text = itemView.context.getString(R.string.gallery_subfolder_count, folder.childCount)
70+
b.tvFolderCount.text = itemView.context.getString(R.string.gallery_folder)
7171
b.root.setOnClickListener { onFolderClick(folder) }
7272
}
7373
}

app/src/main/java/com/degard/imagecompressor/MainActivity.kt

Lines changed: 15 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class MainActivity : AppCompatActivity() {
1313

1414
private lateinit var binding: ActivityMainBinding
1515
private val pathStack = mutableListOf<PathEntry>()
16+
@Volatile private var loadGeneration = 0
1617

1718
data class PathEntry(val uri: Uri, val title: String)
1819

@@ -63,12 +64,6 @@ class MainActivity : AppCompatActivity() {
6364
if (pathStack.isNotEmpty()) {
6465
FolderCache.invalidate(pathStack.last().uri)
6566
loadCurrentLevel()
66-
} else {
67-
val savedUri = Prefs(this).galleryRootUri
68-
if (savedUri != null) {
69-
pathStack.add(PathEntry(savedUri, getString(R.string.gallery_title)))
70-
loadCurrentLevel()
71-
}
7267
}
7368
}
7469

@@ -82,6 +77,7 @@ class MainActivity : AppCompatActivity() {
8277
}
8378

8479
showEmptyState(false)
80+
binding.progressBar.visibility = View.GONE
8581

8682
val cached = FolderCache.get(entry.uri)
8783
if (cached != null) {
@@ -90,28 +86,32 @@ class MainActivity : AppCompatActivity() {
9086
binding.progressBar.visibility = View.VISIBLE
9187
}
9288

89+
val gen = ++loadGeneration
9390
Thread {
9491
try {
9592
val children = queryChildren(entry.uri)
93+
if (gen != loadGeneration) return@Thread
9694
FolderCache.put(entry.uri, children)
9795
runOnUiThread {
98-
binding.progressBar.visibility = View.GONE
99-
displayEntries(children)
100-
if (children.isEmpty()) showEmptyState(true)
96+
if (gen == loadGeneration) {
97+
binding.progressBar.visibility = View.GONE
98+
displayEntries(children)
99+
if (children.isEmpty()) showEmptyState(true)
100+
}
101101
}
102102
} catch (e: Exception) {
103103
runOnUiThread {
104-
binding.progressBar.visibility = View.GONE
105-
if (cached == null) {
106-
showEmptyState(true)
104+
if (gen == loadGeneration) {
105+
binding.progressBar.visibility = View.GONE
106+
if (cached == null) showEmptyState(true)
107107
}
108108
}
109109
}
110110
}.start()
111111
}
112112

113113
private fun displayEntries(entries: List<FolderCache.CachedEntry>) {
114-
val folders = entries.filter { it.isDirectory && it.imageCount > 0 }
114+
val folders = entries.filter { it.isDirectory }
115115
.map { GalleryAdapter.FolderEntry(it.name, Uri.parse(it.uri), it.imageCount) }
116116
val images = mutableListOf<GalleryAdapter.ImageEntry>()
117117
var imgIndex = 0
@@ -150,12 +150,10 @@ class MainActivity : AppCompatActivity() {
150150

151151
val childUri = DocumentsContract.buildDocumentUriUsingTree(parentUri, docId)
152152

153-
val imageCount = if (isDir) {
154-
countImagesFast(parentUri, docId)
155-
} else {
153+
val imageCount = if (!isDir) {
156154
val ext = name.substringAfterLast('.', "").lowercase()
157155
if (ext in imageExtensions) 1 else 0
158-
}
156+
} else 0
159157

160158
entries.add(
161159
FolderCache.CachedEntry(
@@ -175,41 +173,6 @@ class MainActivity : AppCompatActivity() {
175173
return entries
176174
}
177175

178-
private fun countImagesFast(treeUri: Uri, documentId: String): Int {
179-
val resolver = contentResolver
180-
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(treeUri, documentId)
181-
182-
var count = 0
183-
var cursor: Cursor? = null
184-
try {
185-
cursor = resolver.query(
186-
childrenUri,
187-
arrayOf(
188-
DocumentsContract.Document.COLUMN_DOCUMENT_ID,
189-
DocumentsContract.Document.COLUMN_DISPLAY_NAME,
190-
DocumentsContract.Document.COLUMN_MIME_TYPE
191-
),
192-
null, null, null
193-
) ?: return 0
194-
195-
while (cursor.moveToNext()) {
196-
val childDocId = cursor.getString(0)
197-
val name = cursor.getString(1) ?: continue
198-
val mime = cursor.getString(2) ?: ""
199-
if (DocumentsContract.Document.MIME_TYPE_DIR == mime) {
200-
count += countImagesFast(treeUri, childDocId)
201-
} else {
202-
val ext = name.substringAfterLast('.', "").lowercase()
203-
if (ext in setOf("jpg", "jpeg", "png", "webp", "heic", "heif")) count++
204-
}
205-
}
206-
} catch (_: Exception) {
207-
} finally {
208-
cursor?.close()
209-
}
210-
return count
211-
}
212-
213176
private fun openFullScreen(index: Int) {
214177
val adapter = binding.rvGallery.adapter as GalleryAdapter
215178
val imageUris = adapter.getImages().map { it.uri.toString() }.toTypedArray()

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<string name="gallery_loading">Loading…</string>
2222
<string name="label_gallery_root">Gallery root folder (for viewing)</string>
2323
<string name="gallery_subfolder_count">%d photos</string>
24+
<string name="gallery_folder">Folder</string>
2425
<string name="rotate">Rotate</string>
2526
<string name="delete">Delete</string>
2627
<string name="confirm_delete_title">Delete photo</string>

0 commit comments

Comments
 (0)