Skip to content

Commit 2493285

Browse files
Merge pull request #15901 from nextcloud/perf/gallery-adapter-caching
perf: gallery adapter caching
2 parents 78a17b7 + 6ede6d6 commit 2493285

File tree

1 file changed

+66
-27
lines changed

1 file changed

+66
-27
lines changed

app/src/main/java/com/owncloud/android/ui/adapter/GalleryAdapter.kt

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import com.owncloud.android.datamodel.FileDataStorageManager
3131
import com.owncloud.android.datamodel.GalleryItems
3232
import com.owncloud.android.datamodel.GalleryRow
3333
import com.owncloud.android.datamodel.OCFile
34+
import com.owncloud.android.lib.common.utils.Log_OC
3435
import com.owncloud.android.ui.activity.ComponentsGetter
3536
import com.owncloud.android.ui.fragment.GalleryFragment
3637
import com.owncloud.android.ui.fragment.GalleryFragmentBottomSheetDialog
@@ -57,7 +58,24 @@ class GalleryAdapter(
5758
) : SectionedRecyclerViewAdapter<SectionedViewHolder>(),
5859
CommonOCFileListAdapterInterface,
5960
PopupTextProvider {
60-
var files: List<GalleryItems> = mutableListOf()
61+
62+
companion object {
63+
private const val TAG = "GalleryAdapter"
64+
}
65+
66+
// fileId -> (section, row)
67+
private val filePositionMap = mutableMapOf<Long, Pair<Int, Int>>()
68+
private var cachedAllFiles: List<OCFile>? = null
69+
private var cachedFilesCount: Int = 0
70+
71+
private var _files: List<GalleryItems> = mutableListOf()
72+
var files: List<GalleryItems>
73+
get() = _files
74+
private set(value) {
75+
_files = value
76+
invalidateCaches()
77+
}
78+
6179
private val ocFileListDelegate: OCFileListDelegate
6280
private var storageManager: FileDataStorageManager = transferServiceGetter.storageManager
6381

@@ -78,6 +96,28 @@ class GalleryAdapter(
7896
)
7997
}
8098

99+
private fun invalidateCaches() {
100+
Log_OC.d(TAG, "invalidating caches")
101+
cachedAllFiles = null
102+
updateFilesCount()
103+
rebuildFilePositionMap()
104+
}
105+
106+
private fun updateFilesCount() {
107+
cachedFilesCount = files.sumOf { it.rows.size }
108+
}
109+
110+
private fun rebuildFilePositionMap() {
111+
filePositionMap.clear()
112+
files.forEachIndexed { sectionIndex, galleryItem ->
113+
galleryItem.rows.forEachIndexed { rowIndex, row ->
114+
row.files.forEach { file ->
115+
filePositionMap[file.fileId] = sectionIndex to rowIndex
116+
}
117+
}
118+
}
119+
}
120+
81121
override fun getItemId(section: Int, position: Int): Long = files[section].rows[position].calculateHashCode()
82122

83123
override fun selectAll(value: Boolean) {
@@ -150,6 +190,7 @@ class GalleryAdapter(
150190
}
151191
}
152192

193+
@SuppressLint("NotifyDataSetChanged")
153194
fun showAllGalleryItems(
154195
remotePath: String,
155196
mediaState: GalleryFragmentBottomSheetDialog.MediaState,
@@ -195,11 +236,14 @@ class GalleryAdapter(
195236
}
196237
}
197238

198-
private fun transformToRows(list: List<OCFile>): List<GalleryRow> = list
199-
.sortedBy { it.modificationTimestamp }
200-
.reversed()
201-
.chunked(columns)
202-
.map { entry -> GalleryRow(entry, defaultThumbnailSize, defaultThumbnailSize) }
239+
private fun transformToRows(list: List<OCFile>): List<GalleryRow> {
240+
if (list.isEmpty()) return emptyList()
241+
242+
return list
243+
.sortedByDescending { it.modificationTimestamp }
244+
.chunked(columns)
245+
.map { chunk -> GalleryRow(chunk, defaultThumbnailSize, defaultThumbnailSize) }
246+
}
203247

204248
@SuppressLint("NotifyDataSetChanged")
205249
fun clear() {
@@ -240,16 +284,8 @@ class GalleryAdapter(
240284
}
241285

242286
override fun getItemPosition(file: OCFile): Int {
243-
val findResult = files
244-
.asSequence()
245-
.flatMapIndexed { itemIndex, item ->
246-
item.rows.withIndex().map { row -> Triple(itemIndex, row.index, row.value) }
247-
}.find {
248-
it.third.files.contains(file)
249-
}
250-
251-
val (item, row) = findResult ?: Triple(0, 0, null)
252-
return getAbsolutePosition(item, row)
287+
val (section, row) = filePositionMap[file.fileId] ?: return -1
288+
return getAbsolutePosition(section, row)
253289
}
254290

255291
override fun addCheckedFile(file: OCFile) {
@@ -268,17 +304,15 @@ class GalleryAdapter(
268304
notifyItemChanged(getItemPosition(file))
269305
}
270306

271-
override fun getFilesCount(): Int = files.fold(0) { acc, item -> acc + item.rows.size }
307+
override fun getFilesCount(): Int = cachedFilesCount
272308

273309
override fun setMultiSelect(boolean: Boolean) {
274310
ocFileListDelegate.isMultiSelect = boolean
275311
}
276312

277-
private fun getAllFiles(): List<OCFile> = files.flatMap { galleryItem ->
278-
galleryItem.rows.flatMap { row ->
279-
row.files
280-
}
281-
}
313+
private fun getAllFiles(): List<OCFile> = cachedAllFiles ?: files.flatMap { galleryItem ->
314+
galleryItem.rows.flatMap { row -> row.files }
315+
}.also { cachedAllFiles = it }
282316

283317
private fun addAllFilesToCheckedFiles() {
284318
val allFiles = getAllFiles()
@@ -309,6 +343,16 @@ class GalleryAdapter(
309343
}
310344
}
311345

346+
private fun List<OCFile>.toGalleryItems(): List<GalleryItems> {
347+
if (isEmpty()) return emptyList()
348+
349+
return groupBy { firstOfMonth(it.modificationTimestamp) }
350+
.map { (date, filesList) ->
351+
GalleryItems(date, transformToRows(filesList))
352+
}
353+
.sortedByDescending { it.date }
354+
}
355+
312356
override fun onBindFooterViewHolder(holder: SectionedViewHolder?, section: Int) = Unit
313357

314358
override fun swapDirectory(
@@ -322,9 +366,4 @@ class GalleryAdapter(
322366
override fun setHighlightedItem(file: OCFile) = Unit
323367

324368
override fun setSortOrder(mFile: OCFile, sortOrder: FileSortOrder) = Unit
325-
326-
private fun List<OCFile>.toGalleryItems(): List<GalleryItems> = this
327-
.groupBy { firstOfMonth(it.modificationTimestamp) }
328-
.map { GalleryItems(it.key, transformToRows(it.value)) }
329-
.sortedBy { it.date }.reversed()
330369
}

0 commit comments

Comments
 (0)