Browse Source

Changes in cover cache. Store covers in external cache dir

len 9 years ago
parent
commit
b8d1a88623

+ 37 - 77
app/src/main/java/eu/kanade/tachiyomi/data/cache/CoverCache.kt

@@ -1,14 +1,11 @@
 package eu.kanade.tachiyomi.data.cache
 
 import android.content.Context
-import android.widget.ImageView
 import com.bumptech.glide.Glide
-import com.bumptech.glide.load.engine.DiskCacheStrategy
 import com.bumptech.glide.load.model.GlideUrl
 import com.bumptech.glide.load.model.LazyHeaders
 import com.bumptech.glide.request.animation.GlideAnimation
 import com.bumptech.glide.request.target.SimpleTarget
-import com.bumptech.glide.signature.StringSignature
 import eu.kanade.tachiyomi.util.DiskUtils
 import java.io.File
 import java.io.IOException
@@ -28,17 +25,15 @@ class CoverCache(private val context: Context) {
     /**
      * Cache directory used for cache management.
      */
-    private val CACHE_DIRNAME = "cover_disk_cache"
-    private val cacheDir: File = File(context.cacheDir, CACHE_DIRNAME)
+    private val cacheDir: File = File(context.externalCacheDir, "cover_disk_cache")
 
     /**
      * Download the cover with Glide and save the file.
      * @param thumbnailUrl url of thumbnail.
      * @param headers      headers included in Glide request.
-     * @param imageView    imageView where picture should be displayed.
+     * @param onReady      function to call when the image is ready
      */
-    @JvmOverloads
-    fun save(thumbnailUrl: String?, headers: LazyHeaders, imageView: ImageView? = null) {
+    fun save(thumbnailUrl: String?, headers: LazyHeaders, onReady: ((File) -> Unit)? = null) {
         // Check if url is empty.
         if (thumbnailUrl.isNullOrEmpty())
             return
@@ -51,12 +46,9 @@ class CoverCache(private val context: Context) {
                     override fun onResourceReady(resource: File, anim: GlideAnimation<in File>) {
                         try {
                             // Copy the cover from Glide's cache to local cache.
-                            copyToLocalCache(thumbnailUrl!!, resource)
+                            copyToCache(thumbnailUrl!!, resource)
 
-                            // Check if imageView isn't null and show picture in imageView.
-                            if (imageView != null) {
-                                loadFromCache(imageView, resource)
-                            }
+                            onReady?.invoke(resource)
                         } catch (e: IOException) {
                             // Do nothing.
                         }
@@ -64,6 +56,35 @@ class CoverCache(private val context: Context) {
                 })
     }
 
+    /**
+     * Save or load the image from cache
+     * @param thumbnailUrl the thumbnail url.
+     * @param headers      headers included in Glide request.
+     * @param onReady      function to call when the image is ready
+     */
+    fun saveOrLoadFromCache(thumbnailUrl: String?, headers: LazyHeaders, onReady: ((File) -> Unit)?) {
+        // Check if url is empty.
+        if (thumbnailUrl.isNullOrEmpty())
+            return
+
+        // If file exist load it otherwise save it.
+        val localCover = getCoverFromCache(thumbnailUrl!!)
+        if (localCover.exists()) {
+            onReady?.invoke(localCover)
+        } else {
+            save(thumbnailUrl, headers, onReady)
+        }
+    }
+
+    /**
+     * Returns the cover from cache.
+     * @param thumbnailUrl the thumbnail url.
+     * @return cover image.
+     */
+    private fun getCoverFromCache(thumbnailUrl: String): File {
+        return File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl))
+    }
+
     /**
      * Copy the given file to this cache.
      * @param thumbnailUrl url of thumbnail.
@@ -71,7 +92,7 @@ class CoverCache(private val context: Context) {
      * @throws IOException if there's any error.
      */
     @Throws(IOException::class)
-    fun copyToLocalCache(thumbnailUrl: String, sourceFile: File) {
+    fun copyToCache(thumbnailUrl: String, sourceFile: File) {
         // Get destination file.
         val destFile = getCoverFromCache(thumbnailUrl)
 
@@ -85,28 +106,19 @@ class CoverCache(private val context: Context) {
      * @throws IOException if there's any error.
      */
     @Throws(IOException::class)
-    fun copyToLocalCache(thumbnailUrl: String, inputStream: InputStream) {
+    fun copyToCache(thumbnailUrl: String, inputStream: InputStream) {
         // Get destination file.
         val destFile = getCoverFromCache(thumbnailUrl)
 
         destFile.outputStream().use { inputStream.copyTo(it) }
     }
 
-    /**
-     * Returns the cover from cache.
-     * @param thumbnailUrl the thumbnail url.
-     * @return cover image.
-     */
-    private fun getCoverFromCache(thumbnailUrl: String): File {
-        return File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl))
-    }
-
     /**
      * Delete the cover file from the cache.
      * @param thumbnailUrl the thumbnail url.
      * @return status of deletion.
      */
-    fun deleteCoverFromCache(thumbnailUrl: String?): Boolean {
+    fun deleteFromCache(thumbnailUrl: String?): Boolean {
         // Check if url is empty.
         if (thumbnailUrl.isNullOrEmpty())
             return false
@@ -116,56 +128,4 @@ class CoverCache(private val context: Context) {
         return file.exists() && file.delete()
     }
 
-    /**
-     * Save or load the image from cache
-     * @param imageView    imageView where picture should be displayed.
-     * @param thumbnailUrl the thumbnail url.
-     * @param headers      headers included in Glide request.
-     */
-    fun saveOrLoadFromCache(imageView: ImageView, thumbnailUrl: String, headers: LazyHeaders) {
-        // If file exist load it otherwise save it.
-        val localCover = getCoverFromCache(thumbnailUrl)
-        if (localCover.exists()) {
-            loadFromCache(imageView, localCover)
-        } else {
-            save(thumbnailUrl, headers, imageView)
-        }
-    }
-
-    /**
-     * Helper method to load the cover from the cache directory into the specified image view.
-     * Glide stores the resized image in its cache to improve performance.
-     * @param imageView imageView where picture should be displayed.
-     * @param file      file to load. Must exist!.
-     */
-    private fun loadFromCache(imageView: ImageView, file: File) {
-        Glide.with(context)
-                .load(file)
-                .diskCacheStrategy(DiskCacheStrategy.RESULT)
-                .centerCrop()
-                .signature(StringSignature(file.lastModified().toString()))
-                .into(imageView)
-    }
-
-    /**
-     * Helper method to load the cover from network into the specified image view.
-     * The source image is stored in Glide's cache so that it can be easily copied to this cache
-     * if the manga is added to the library.
-     * @param imageView    imageView where picture should be displayed.
-     * @param thumbnailUrl url of thumbnail.
-     * @param headers      headers included in Glide request.
-     */
-    fun loadFromNetwork(imageView: ImageView, thumbnailUrl: String?, headers: LazyHeaders) {
-        // Check if url is empty.
-        if (thumbnailUrl.isNullOrEmpty())
-            return
-
-        val url = GlideUrl(thumbnailUrl, headers)
-        Glide.with(context)
-                .load(url)
-                .diskCacheStrategy(DiskCacheStrategy.SOURCE)
-                .centerCrop()
-                .into(imageView)
-    }
-
 }

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueAdapter.kt

@@ -12,7 +12,7 @@ import java.util.*
  *
  * @param fragment the fragment containing this adapter.
  */
-class CatalogueAdapter(private val fragment: CatalogueFragment) : FlexibleAdapter<CatalogueHolder, Manga>() {
+class CatalogueAdapter(val fragment: CatalogueFragment) : FlexibleAdapter<CatalogueHolder, Manga>() {
 
     /**
      * Property to get the list of manga in the adapter.
@@ -83,7 +83,7 @@ class CatalogueAdapter(private val fragment: CatalogueFragment) : FlexibleAdapte
      */
     override fun onBindViewHolder(holder: CatalogueHolder, position: Int) {
         val manga = getItem(position)
-        holder.onSetValues(manga, fragment.presenter)
+        holder.onSetValues(manga)
     }
 
 }

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt

@@ -370,7 +370,7 @@ class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleViewHold
      * @param manga the manga initialized
      */
     fun onMangaInitialized(manga: Manga) {
-        getHolder(manga)?.setImage(manga, presenter)
+        getHolder(manga)?.setImage(manga)
     }
 
     /**

+ 16 - 8
app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.kt

@@ -1,6 +1,9 @@
 package eu.kanade.tachiyomi.ui.catalogue
 
 import android.view.View
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.bumptech.glide.load.model.GlideUrl
 import eu.kanade.tachiyomi.data.database.models.Manga
 import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
 
@@ -13,7 +16,7 @@ import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
  * @param listener a listener to react to single tap and long tap events.
  * @constructor creates a new catalogue holder.
  */
-class CatalogueGridHolder(private val view: View, adapter: CatalogueAdapter, listener: OnListItemClickListener) :
+class CatalogueGridHolder(private val view: View, private val adapter: CatalogueAdapter, listener: OnListItemClickListener) :
         CatalogueHolder(view, adapter, listener) {
 
     /**
@@ -21,16 +24,15 @@ class CatalogueGridHolder(private val view: View, adapter: CatalogueAdapter, lis
      * holder with the given manga.
      *
      * @param manga the manga to bind.
-     * @param presenter the catalogue presenter.
      */
-    override fun onSetValues(manga: Manga, presenter: CataloguePresenter) {
+    override fun onSetValues(manga: Manga) {
         // Set manga title
         view.title.text = manga.title
 
         // Set alpha of thumbnail.
         view.thumbnail.alpha = if (manga.favorite) 0.3f else 1.0f
 
-        setImage(manga, presenter)
+        setImage(manga)
     }
 
     /**
@@ -38,12 +40,18 @@ class CatalogueGridHolder(private val view: View, adapter: CatalogueAdapter, lis
      * and the url is now known.
      *
      * @param manga the manga to bind.
-     * @param presenter the catalogue presenter.
      */
-    fun setImage(manga: Manga, presenter: CataloguePresenter) {
+    fun setImage(manga: Manga) {
         if (manga.thumbnail_url != null) {
-            presenter.coverCache.loadFromNetwork(view.thumbnail, manga.thumbnail_url,
-                    presenter.source.glideHeaders)
+            val url = manga.thumbnail_url!!
+            val headers = adapter.fragment.presenter.source.glideHeaders
+
+            Glide.with(view.context)
+                    .load(if (headers != null) GlideUrl(url, headers) else url)
+                    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
+                    .centerCrop()
+                    .into(view.thumbnail)
+
         } else {
             view.thumbnail.setImageResource(android.R.color.transparent)
         }

+ 1 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueHolder.kt

@@ -19,7 +19,6 @@ abstract class CatalogueHolder(view: View, adapter: CatalogueAdapter, listener:
      * holder with the given manga.
      *
      * @param manga the manga to bind.
-     * @param presenter the catalogue presenter.
      */
-    abstract fun onSetValues(manga: Manga, presenter: CataloguePresenter)
+    abstract fun onSetValues(manga: Manga)
 }

+ 1 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueListHolder.kt

@@ -25,9 +25,8 @@ class CatalogueListHolder(private val view: View, adapter: CatalogueAdapter, lis
      * holder with the given manga.
      *
      * @param manga the manga to bind.
-     * @param presenter the catalogue presenter.
      */
-    override fun onSetValues(manga: Manga, presenter: CataloguePresenter) {
+    override fun onSetValues(manga: Manga) {
         view.title.text = manga.title
         view.title.setTextColor(if (manga.favorite) favoriteColor else unfavoriteColor)
     }

+ 0 - 6
app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CataloguePresenter.kt

@@ -1,7 +1,6 @@
 package eu.kanade.tachiyomi.ui.catalogue
 
 import android.os.Bundle
-import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.database.DatabaseHelper
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@@ -33,11 +32,6 @@ class CataloguePresenter : BasePresenter<CatalogueFragment>() {
      */
     @Inject lateinit var db: DatabaseHelper
 
-    /**
-     * Cover cache.
-     */
-    @Inject lateinit var coverCache: CoverCache
-
     /**
      * Preferences.
      */

+ 21 - 5
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt

@@ -1,6 +1,9 @@
 package eu.kanade.tachiyomi.ui.library
 
 import android.view.View
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.bumptech.glide.signature.StringSignature
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.source.base.Source
@@ -16,9 +19,11 @@ import kotlinx.android.synthetic.main.item_catalogue_grid.view.*
  * @param listener a listener to react to single tap and long tap events.
  * @constructor creates a new library holder.
  */
-class LibraryHolder(view: View, adapter: LibraryCategoryAdapter, listener: FlexibleViewHolder.OnListItemClickListener) :
+class LibraryHolder(private val view: View, adapter: LibraryCategoryAdapter, listener: FlexibleViewHolder.OnListItemClickListener) :
         FlexibleViewHolder(view, adapter, listener) {
 
+    private var manga: Manga? = null
+
     /**
      * Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this
      * holder with the given manga.
@@ -27,11 +32,13 @@ class LibraryHolder(view: View, adapter: LibraryCategoryAdapter, listener: Flexi
      * @param presenter the library presenter.
      */
     fun onSetValues(manga: Manga, presenter: LibraryPresenter) {
+        this.manga = manga
+
         // Update the title of the manga.
-        itemView.title.text = manga.title
+        view.title.text = manga.title
 
         // Update the unread count and its visibility.
-        with(itemView.unreadText) {
+        with(view.unreadText) {
             visibility = if (manga.unread > 0) View.VISIBLE else View.GONE
             text = manga.unread.toString()
         }
@@ -49,9 +56,18 @@ class LibraryHolder(view: View, adapter: LibraryCategoryAdapter, listener: Flexi
      */
     private fun loadCover(manga: Manga, source: Source, coverCache: CoverCache) {
         if (manga.thumbnail_url != null) {
-            coverCache.saveOrLoadFromCache(itemView.thumbnail, manga.thumbnail_url, source.glideHeaders)
+            coverCache.saveOrLoadFromCache(manga.thumbnail_url, source.glideHeaders) {
+                if (this.manga == manga) {
+                    Glide.with(view.context)
+                            .load(it)
+                            .diskCacheStrategy(DiskCacheStrategy.RESULT)
+                            .centerCrop()
+                            .signature(StringSignature(it.lastModified().toString()))
+                            .into(itemView.thumbnail)
+                }
+            }
         } else {
-            itemView.thumbnail.setImageResource(android.R.color.transparent)
+            view.thumbnail.setImageResource(android.R.color.transparent)
         }
     }
 

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -280,7 +280,7 @@ class LibraryPresenter : BasePresenter<LibraryFragment>() {
     @Throws(IOException::class)
     fun editCoverWithStream(inputStream: InputStream, manga: Manga): Boolean {
         if (manga.thumbnail_url != null && manga.favorite) {
-            coverCache.copyToLocalCache(manga.thumbnail_url, inputStream)
+            coverCache.copyToCache(manga.thumbnail_url, inputStream)
             return true
         }
         return false

+ 34 - 19
app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.kt

@@ -4,6 +4,10 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.bumptech.glide.load.model.GlideUrl
+import com.bumptech.glide.signature.StringSignature
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.source.base.Source
@@ -95,26 +99,37 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
         val headers = presenter.source.glideHeaders
 
         // Check if thumbnail_url is given.
-        if (manga.thumbnail_url != null) {
-            // Check if cover is already drawn.
-            if (manga_cover.drawable == null) {
-                // If manga is in library then (download / save) (from / to) local cache if available,
-                // else download from network.
-                if (manga.favorite) {
-                    coverCache.saveOrLoadFromCache(manga_cover, manga.thumbnail_url, headers)
-                } else {
-                    coverCache.loadFromNetwork(manga_cover, manga.thumbnail_url, headers)
-                }
-            }
-            // Check if backdrop is already drawn.
-            if (backdrop.drawable == null) {
-                // If manga is in library then (download / save) (from / to) local cache if available,
-                // else download from network.
-                if (manga.favorite) {
-                    coverCache.saveOrLoadFromCache(backdrop, manga.thumbnail_url, headers)
-                } else {
-                    coverCache.loadFromNetwork(backdrop, manga.thumbnail_url, headers)
+        manga.thumbnail_url?.let { url ->
+            if (manga.favorite) {
+                coverCache.saveOrLoadFromCache(url, headers) {
+                    if (isResumed) {
+                        Glide.with(context)
+                                .load(it)
+                                .diskCacheStrategy(DiskCacheStrategy.RESULT)
+                                .centerCrop()
+                                .signature(StringSignature(it.lastModified().toString()))
+                                .into(manga_cover)
+
+                        Glide.with(context)
+                                .load(it)
+                                .diskCacheStrategy(DiskCacheStrategy.RESULT)
+                                .centerCrop()
+                                .signature(StringSignature(it.lastModified().toString()))
+                                .into(backdrop)
+                    }
                 }
+            } else {
+                Glide.with(context)
+                        .load(if (headers != null) GlideUrl(url, headers) else url)
+                        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
+                        .centerCrop()
+                        .into(manga_cover)
+
+                Glide.with(context)
+                        .load(if (headers != null) GlideUrl(url, headers) else url)
+                        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
+                        .centerCrop()
+                        .into(backdrop)
             }
         }
     }

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt

@@ -130,7 +130,7 @@ class MangaInfoPresenter : BasePresenter<MangaInfoFragment>() {
         if (isFavorite) {
             coverCache.save(manga.thumbnail_url, source.glideHeaders)
         } else {
-            coverCache.deleteCoverFromCache(manga.thumbnail_url)
+            coverCache.deleteFromCache(manga.thumbnail_url)
         }
     }