Minor refactor on caches

This commit is contained in:
inorichi 2016-01-28 01:01:55 +01:00
parent d8ab8f297f
commit 74c32f9e16
3 changed files with 77 additions and 120 deletions

View File

@ -44,12 +44,15 @@ public class ChapterCache {
/** Interface to global information about an application environment. */ /** Interface to global information about an application environment. */
private final Context context; private final Context context;
/** Google Json class used for parsing json files. */ /** Google Json class used for parsing JSON files. */
private final Gson gson; private final Gson gson;
/** Cache class used for cache management. */ /** Cache class used for cache management. */
private DiskLruCache diskCache; private DiskLruCache diskCache;
/** Page list collection used for deserializing from JSON. */
private final Type pageListCollection;
/** /**
* Constructor of ChapterCache. * Constructor of ChapterCache.
* @param context application environment interface. * @param context application environment interface.
@ -69,28 +72,10 @@ public class ChapterCache {
PARAMETER_CACHE_SIZE PARAMETER_CACHE_SIZE
); );
} catch (IOException e) { } catch (IOException e) {
// Do Nothing. TODO error handling. // Do Nothing.
}
} }
/** pageListCollection = new TypeToken<List<Page>>() {}.getType();
* Remove file from cache.
* @param file name of chapter file md5.0.
* @return false if file is journal or error else returns status of deletion.
*/
public boolean removeFileFromCache(String file) {
// Make sure we don't delete the journal file (keeps track of cache).
if (file.equals("journal") || file.startsWith("journal."))
return false;
try {
// Take dot(.) substring to get filename without the .0 at the end.
String key = file.substring(0, file.lastIndexOf("."));
// Remove file from cache.
return diskCache.remove(key);
} catch (IOException e) {
return false;
}
} }
/** /**
@ -118,64 +103,57 @@ public class ChapterCache {
} }
/** /**
* Get page objects from cache. * Remove file from cache.
* @param chapterUrl the url of the chapter. * @param file name of file "md5.0".
* @return list of chapter pages. * @return status of deletion for the file.
*/ */
public Observable<List<Page>> getPageUrlsFromDiskCache(final String chapterUrl) { public boolean removeFileFromCache(String file) {
return Observable.create(subscriber -> { // Make sure we don't delete the journal file (keeps track of cache).
if (file.equals("journal") || file.startsWith("journal."))
return false;
try { try {
// Get list of pages from chapterUrl. // Remove the extension from the file to get the key of the cache
List<Page> pages = getPageUrlsFromDiskCacheImpl(chapterUrl); String key = file.substring(0, file.lastIndexOf("."));
// Provides the Observer with a new item to observe. // Remove file from cache.
subscriber.onNext(pages); return diskCache.remove(key);
// Notify the Observer that finished sending push-based notifications. } catch (IOException e) {
subscriber.onCompleted(); return false;
} catch (Throwable e) {
subscriber.onError(e);
} }
});
} }
/** /**
* Implementation of the getPageUrlsFromDiskCache() function * Get page list from cache.
* @param chapterUrl the url of the chapter * @param chapterUrl the url of the chapter.
* @return returns list of chapter pages * @return an observable of the list of pages.
* @throws IOException does nothing atm
*/ */
private List<Page> getPageUrlsFromDiskCacheImpl(String chapterUrl) throws IOException /*TODO IOException never thrown*/ { public Observable<List<Page>> getPageListFromCache(final String chapterUrl) {
return Observable.fromCallable(() -> {
// Initialize snapshot (a snapshot of the values for an entry). // Initialize snapshot (a snapshot of the values for an entry).
DiskLruCache.Snapshot snapshot = null; DiskLruCache.Snapshot snapshot = null;
// Initialize list of pages.
List<Page> pages = null;
try { try {
// Create md5 key and retrieve snapshot. // Create md5 key and retrieve snapshot.
String key = DiskUtils.hashKeyForDisk(chapterUrl); String key = DiskUtils.hashKeyForDisk(chapterUrl);
snapshot = diskCache.get(key); snapshot = diskCache.get(key);
// Convert JSON string to list of objects. // Convert JSON string to list of objects.
Type collectionType = new TypeToken<List<Page>>() {}.getType(); return gson.fromJson(snapshot.getString(0), pageListCollection);
pages = gson.fromJson(snapshot.getString(0), collectionType);
} catch (IOException e) {
// Do Nothing. //TODO error handling?
} finally { } finally {
if (snapshot != null) { if (snapshot != null) {
snapshot.close(); snapshot.close();
} }
} }
return pages; });
} }
/** /**
* Add page urls to disk cache. * Add page list to disk cache.
* @param chapterUrl the url of the chapter. * @param chapterUrl the url of the chapter.
* @param pages list of chapter pages. * @param pages list of pages.
*/ */
public void putPageUrlsToDiskCache(final String chapterUrl, final List<Page> pages) { public void putPageListToCache(final String chapterUrl, final List<Page> pages) {
// Convert list of pages to json string. // Convert list of pages to json string.
String cachedValue = gson.toJson(pages); String cachedValue = gson.toJson(pages);
@ -201,7 +179,7 @@ public class ChapterCache {
diskCache.flush(); diskCache.flush();
editor.commit(); editor.commit();
} catch (Exception e) { } catch (Exception e) {
// Do Nothing. TODO error handling? // Do Nothing.
} finally { } finally {
if (editor != null) { if (editor != null) {
editor.abortUnlessCommitted(); editor.abortUnlessCommitted();
@ -210,7 +188,7 @@ public class ChapterCache {
try { try {
outputStream.close(); outputStream.close();
} catch (IOException ignore) { } catch (IOException ignore) {
// Do Nothing. TODO error handling? // Do Nothing.
} }
} }
} }
@ -225,10 +203,9 @@ public class ChapterCache {
try { try {
return diskCache.get(DiskUtils.hashKeyForDisk(imageUrl)) != null; return diskCache.get(DiskUtils.hashKeyForDisk(imageUrl)) != null;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace();
}
return false; return false;
} }
}
/** /**
* Get image path from url. * Get image path from url.
@ -242,18 +219,17 @@ public class ChapterCache {
File file = new File(diskCache.getDirectory(), imageName); File file = new File(diskCache.getDirectory(), imageName);
return file.getCanonicalPath(); return file.getCanonicalPath();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace();
}
return null; return null;
} }
}
/** /**
* Add image to cache * Add image to cache.
* @param imageUrl url of image. * @param imageUrl url of image.
* @param response http response from page. * @param response http response from page.
* @throws IOException image error. * @throws IOException image error.
*/ */
public void putImageToDiskCache(final String imageUrl, final Response response) throws IOException { public void putImageToCache(final String imageUrl, final Response response) throws IOException {
// Initialize editor (edits the values for an entry). // Initialize editor (edits the values for an entry).
DiskLruCache.Editor editor = null; DiskLruCache.Editor editor = null;
@ -276,6 +252,7 @@ public class ChapterCache {
diskCache.flush(); diskCache.flush();
editor.commit(); editor.commit();
} catch (Exception e) { } catch (Exception e) {
response.body().close();
throw new IOException("Unable to save image"); throw new IOException("Unable to save image");
} finally { } finally {
if (editor != null) { if (editor != null) {
@ -285,7 +262,6 @@ public class ChapterCache {
sink.close(); sink.close();
} }
} }
} }
} }

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.data.cache; package eu.kanade.tachiyomi.data.cache;
import android.content.Context; import android.content.Context;
import android.support.annotation.Nullable;
import android.text.TextUtils; import android.text.TextUtils;
import android.widget.ImageView; import android.widget.ImageView;
@ -22,8 +23,8 @@ import eu.kanade.tachiyomi.util.DiskUtils;
/** /**
* Class used to create cover cache * Class used to create cover cache
* Makes use of Glide(which can avoid repeating requests) for saving the file. * It is used to store the covers of the library.
* It is not necessary to load the images to the cache. * Makes use of Glide (which can avoid repeating requests) to download covers.
* Names of files are created with the md5 of the thumbnail URL * Names of files are created with the md5 of the thumbnail URL
*/ */
public class CoverCache { public class CoverCache {
@ -39,7 +40,7 @@ public class CoverCache {
private final Context context; private final Context context;
/** /**
* Cache class used for cache management. * Cache directory used for cache management.
*/ */
private final File cacheDir; private final File cacheDir;
@ -59,16 +60,16 @@ public class CoverCache {
} }
/** /**
* Check if cache dir exist if not create directory. * Create cache directory if it doesn't exist
* *
* @return true if cache dir does exist and is created. * @return true if cache dir is created otherwise false.
*/ */
private boolean createCacheDir() { private boolean createCacheDir() {
return !cacheDir.exists() && cacheDir.mkdirs(); return !cacheDir.exists() && cacheDir.mkdirs();
} }
/** /**
* Download the cover with Glide (it can avoid repeating requests) and save the file. * Download the cover with Glide and save the file in this cache.
* *
* @param thumbnailUrl url of thumbnail. * @param thumbnailUrl url of thumbnail.
* @param headers headers included in Glide request. * @param headers headers included in Glide request.
@ -78,17 +79,15 @@ public class CoverCache {
} }
/** /**
* Download the cover with Glide (it can avoid repeating requests) and save the file. * Download the cover with Glide and save the file.
* *
* @param thumbnailUrl url of thumbnail. * @param thumbnailUrl url of thumbnail.
* @param headers headers included in Glide request. * @param headers headers included in Glide request.
* @param imageView imageView where picture should be displayed. * @param imageView imageView where picture should be displayed.
*/ */
private void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) { private void save(String thumbnailUrl, LazyHeaders headers, @Nullable ImageView imageView) {
// Check if url is empty. // Check if url is empty.
if (TextUtils.isEmpty(thumbnailUrl)) if (TextUtils.isEmpty(thumbnailUrl))
// Do not try and create the string. Instead... only try to realize the truth. There is no string.
return; return;
// Download the cover with Glide and save the file. // Download the cover with Glide and save the file.
@ -107,29 +106,27 @@ public class CoverCache {
loadFromCache(imageView, resource); loadFromCache(imageView, resource);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); // Do nothing.
} }
} }
}); });
} }
/** /**
* Copy the cover from Glide's cache to local cache. * Copy the cover from Glide's cache to this cache.
* *
* @param thumbnailUrl url of thumbnail. * @param thumbnailUrl url of thumbnail.
* @param source the cover image. * @param source the cover image.
* @throws IOException TODO not returned atm? * @throws IOException exception returned
*/ */
private void copyToLocalCache(String thumbnailUrl, File source) throws IOException { private void copyToLocalCache(String thumbnailUrl, File source) throws IOException {
// Create cache directory and check if directory exist // Create cache directory if needed.
createCacheDir(); createCacheDir();
// Create destination file. // Get destination file.
File dest = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl)); File dest = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl));
// Delete the current file if it exists.
// Check if file already exists, if true delete it.
if (dest.exists()) if (dest.exists())
dest.delete(); dest.delete();
@ -196,26 +193,9 @@ public class CoverCache {
} }
} }
/**
* If the image is already in our cache, use it. If not, load it with glide.
* TODO not used atm.
*
* @param imageView imageView where picture should be displayed.
* @param thumbnailUrl url of thumbnail.
* @param headers headers included in Glide request.
*/
public void loadFromCacheOrNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) {
// If localCover exist load it from cache otherwise load it from network.
File localCover = getCoverFromCache(thumbnailUrl);
if (localCover.exists()) {
loadFromCache(imageView, localCover);
} else {
loadFromNetwork(imageView, thumbnailUrl, headers);
}
}
/** /**
* Helper method to load the cover from the cache directory into the specified image view. * 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 imageView imageView where picture should be displayed.
* @param file file to load. Must exist!. * @param file file to load. Must exist!.
@ -230,7 +210,8 @@ public class CoverCache {
/** /**
* Helper method to load the cover from network into the specified image view. * Helper method to load the cover from network into the specified image view.
* It does NOT save the image in cache! * 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 imageView imageView where picture should be displayed.
* @param thumbnailUrl url of thumbnail. * @param thumbnailUrl url of thumbnail.

View File

@ -93,7 +93,7 @@ public abstract class Source extends BaseSource {
} }
public Observable<List<Page>> getCachedPageListOrPullFromNetwork(final String chapterUrl) { public Observable<List<Page>> getCachedPageListOrPullFromNetwork(final String chapterUrl) {
return chapterCache.getPageUrlsFromDiskCache(getChapterCacheKey(chapterUrl)) return chapterCache.getPageListFromCache(getChapterCacheKey(chapterUrl))
.onErrorResumeNext(throwable -> { .onErrorResumeNext(throwable -> {
return pullPageListFromNetwork(chapterUrl); return pullPageListFromNetwork(chapterUrl);
}) })
@ -168,7 +168,7 @@ public abstract class Source extends BaseSource {
return getImageProgressResponse(page) return getImageProgressResponse(page)
.flatMap(resp -> { .flatMap(resp -> {
try { try {
chapterCache.putImageToDiskCache(page.getImageUrl(), resp); chapterCache.putImageToCache(page.getImageUrl(), resp);
} catch (IOException e) { } catch (IOException e) {
return Observable.error(e); return Observable.error(e);
} }
@ -182,7 +182,7 @@ public abstract class Source extends BaseSource {
public void savePageList(String chapterUrl, List<Page> pages) { public void savePageList(String chapterUrl, List<Page> pages) {
if (pages != null) if (pages != null)
chapterCache.putPageUrlsToDiskCache(getChapterCacheKey(chapterUrl), pages); chapterCache.putPageListToCache(getChapterCacheKey(chapterUrl), pages);
} }
protected List<Page> convertToPages(List<String> pageUrls) { protected List<Page> convertToPages(List<String> pageUrls) {