Clean up ChapterCache (remove Gson, Rx usage)

(cherry picked from commit 356b7c346aba9dd0fafbb089c56de11ac50d1065)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt
This commit is contained in:
arkon 2021-04-18 11:03:55 -04:00 committed by Jobobby04
parent e43777bba7
commit d3778ac6e1
3 changed files with 60 additions and 66 deletions

View File

@ -2,8 +2,6 @@ package eu.kanade.tachiyomi.data.cache
import android.content.Context import android.content.Context
import android.text.format.Formatter import android.text.format.Formatter
import com.github.salomonbrys.kotson.fromJson
import com.google.gson.Gson
import com.jakewharton.disklrucache.DiskLruCache import com.jakewharton.disklrucache.DiskLruCache
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -15,10 +13,12 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.Response import okhttp3.Response
import okio.buffer import okio.buffer
import okio.sink import okio.sink
import rx.Observable
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
@ -48,14 +48,12 @@ class ChapterCache(private val context: Context) {
private val scope = CoroutineScope(Job() + Dispatchers.Main) private val scope = CoroutineScope(Job() + Dispatchers.Main)
/** Google Json class used for parsing JSON files. */ /** Google Json class used for parsing JSON files. */
private val gson: Gson by injectLazy() private val json: Json by injectLazy()
// --> EH // --> EH
private val prefs: PreferencesHelper by injectLazy() private val prefs: PreferencesHelper by injectLazy()
// <-- EH
/** Cache class used for cache management. */ /** Cache class used for cache management. */
// --> EH
private var diskCache = setupDiskCache(prefs.cacheSize().get().toLong()) private var diskCache = setupDiskCache(prefs.cacheSize().get().toLong())
init { init {
@ -73,7 +71,7 @@ class ChapterCache(private val context: Context) {
/** /**
* Returns directory of cache. * Returns directory of cache.
*/ */
val cacheDir: File private val cacheDir: File
get() = diskCache.directory get() = diskCache.directory
/** /**
@ -100,43 +98,19 @@ class ChapterCache(private val context: Context) {
} }
// <-- EH // <-- EH
/**
* Remove file from cache.
*
* @param file name of file "md5.0".
* @return status of deletion for the file.
*/
fun removeFileFromCache(file: String): Boolean {
// Make sure we don't delete the journal file (keeps track of cache).
if (file == "journal" || file.startsWith("journal.")) {
return false
}
return try {
// Remove the extension from the file to get the key of the cache
val key = file.substringBeforeLast(".")
// Remove file from cache.
diskCache.remove(key)
} catch (e: Exception) {
false
}
}
/** /**
* Get page list from cache. * Get page list from cache.
* *
* @param chapter the chapter. * @param chapter the chapter.
* @return an observable of the list of pages. * @return the list of pages.
*/ */
fun getPageListFromCache(chapter: Chapter): Observable<List<Page>> { fun getPageListFromCache(chapter: Chapter): List<Page> {
return Observable.fromCallable { // Get the key for the chapter.
// Get the key for the chapter. val key = DiskUtil.hashKeyForDisk(getKey(chapter))
val key = DiskUtil.hashKeyForDisk(getKey(chapter))
// Convert JSON string to list of objects. Throws an exception if snapshot is null // Convert JSON string to list of objects. Throws an exception if snapshot is null
diskCache.get(key).use { return diskCache.get(key).use {
gson.fromJson<List<Page>>(it.getString(0)) json.decodeFromString(it.getString(0))
}
} }
} }
@ -148,7 +122,7 @@ class ChapterCache(private val context: Context) {
*/ */
fun putPageListToCache(chapter: Chapter, pages: List<Page>) { fun putPageListToCache(chapter: Chapter, pages: List<Page>) {
// Convert list of pages to json string. // Convert list of pages to json string.
val cachedValue = gson.toJson(pages) val cachedValue = json.encodeToString(pages)
// Initialize the editor (edits the values for an entry). // Initialize the editor (edits the values for an entry).
var editor: DiskLruCache.Editor? = null var editor: DiskLruCache.Editor? = null
@ -228,6 +202,38 @@ class ChapterCache(private val context: Context) {
} }
} }
fun clear(): Int {
var deletedFiles = 0
cacheDir.listFiles()?.forEach {
if (removeFileFromCache(it.name)) {
deletedFiles++
}
}
return deletedFiles
}
/**
* Remove file from cache.
*
* @param file name of file "md5.0".
* @return status of deletion for the file.
*/
private fun removeFileFromCache(file: String): Boolean {
// Make sure we don't delete the journal file (keeps track of cache).
if (file == "journal" || file.startsWith("journal.")) {
return false
}
return try {
// Remove the extension from the file to get the key of the cache
val key = file.substringBeforeLast(".")
// Remove file from cache.
diskCache.remove(key)
} catch (e: Exception) {
false
}
}
private fun getKey(chapter: Chapter): String { private fun getKey(chapter: Chapter): String {
return "${chapter.manga_id}${chapter.url}" return "${chapter.manga_id}${chapter.url}"
} }

View File

@ -99,8 +99,7 @@ class HttpPageLoader(
* the local cache, otherwise fallbacks to network. * the local cache, otherwise fallbacks to network.
*/ */
override fun getPages(): Observable<List<ReaderPage>> { override fun getPages(): Observable<List<ReaderPage>> {
return chapterCache return Observable.fromCallable { chapterCache.getPageListFromCache(chapter.chapter) }
.getPageListFromCache(chapter.chapter)
.onErrorResumeNext { source.fetchPageList(chapter.chapter) } .onErrorResumeNext { source.fetchPageList(chapter.chapter) }
.map { pages -> .map { pages ->
// SY --> // SY -->

View File

@ -29,7 +29,8 @@ import eu.kanade.tachiyomi.source.SourceManager.Companion.DELEGATED_SOURCES
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.util.CrashLogUtil import eu.kanade.tachiyomi.util.CrashLogUtil
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.defaultValue
import eu.kanade.tachiyomi.util.preference.editTextPreference import eu.kanade.tachiyomi.util.preference.editTextPreference
import eu.kanade.tachiyomi.util.preference.intListPreference import eu.kanade.tachiyomi.util.preference.intListPreference
@ -53,9 +54,6 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -372,8 +370,8 @@ class SettingsAdvancedController : SettingsController() {
foldersCleared += downloadManager.cleanupChapters(chapterList, manga, source, removeRead, removeNonFavorite) foldersCleared += downloadManager.cleanupChapters(chapterList, manga, source, removeRead, removeNonFavorite)
} }
} }
launchUI { withUIContext {
val activity = activity ?: return@launchUI val activity = activity ?: return@withUIContext
val cleanupString = val cleanupString =
if (foldersCleared == 0) activity.getString(R.string.no_folders_to_cleanup) if (foldersCleared == 0) activity.getString(R.string.no_folders_to_cleanup)
else resources!!.getQuantityString( else resources!!.getQuantityString(
@ -389,27 +387,18 @@ class SettingsAdvancedController : SettingsController() {
private fun clearChapterCache() { private fun clearChapterCache() {
if (activity == null) return if (activity == null) return
val files = chapterCache.cacheDir.listFiles() ?: return launchIO {
try {
var deletedFiles = 0 val deletedFiles = chapterCache.clear()
withUIContext {
Observable.defer { Observable.from(files) } activity?.toast(resources?.getString(R.string.cache_deleted, deletedFiles))
.doOnNext { file -> findPreference(CLEAR_CACHE_KEY)?.summary =
if (chapterCache.removeFileFromCache(file.name)) { resources?.getString(R.string.used_cache, chapterCache.readableSize)
deletedFiles++
} }
} catch (e: Throwable) {
withUIContext { activity?.toast(R.string.cache_delete_error) }
} }
.subscribeOn(Schedulers.io()) }
.observeOn(AndroidSchedulers.mainThread())
.doOnError {
activity?.toast(R.string.cache_delete_error)
}
.doOnCompleted {
activity?.toast(resources?.getString(R.string.cache_deleted, deletedFiles))
findPreference(CLEAR_CACHE_KEY)?.summary =
resources?.getString(R.string.used_cache, chapterCache.readableSize)
}
.subscribe()
} }
class ClearDatabaseDialogController : DialogController() { class ClearDatabaseDialogController : DialogController() {