Code optimization. Added javadoc. Removed setSize for it is not used

Fixed some mistakes.

Code optimization. Added comments. Few comment mistake fixes

Few comments

Added classes because of renaming

Fixed refactor mistakes :(.

typo + removed todo empty class

Changed o to 0. Some renaming.  Checked for nullability on string.isEmpty() function to prevent crashes

Removed redundant null check

Update ChapterCache.java

Another o to 0 change. Damn this .o! :)
This commit is contained in:
NoodleMage 2016-01-26 13:26:41 +01:00
parent 0c9bc97fe8
commit 23a6f76c37
7 changed files with 256 additions and 48 deletions

View File

@ -21,22 +21,46 @@ import okio.BufferedSink;
import okio.Okio;
import rx.Observable;
/**
* Class used to create chapter cache
* For each image in a chapter a file is created
* For each chapter a Json list is created and converted to a file.
* The files are in format *md5key*.0
*/
public class ChapterCache {
/** Name of cache directory. */
private static final String PARAMETER_CACHE_DIRECTORY = "chapter_disk_cache";
/** Application cache version. */
private static final int PARAMETER_APP_VERSION = 1;
/** The number of values per cache entry. Must be positive. */
private static final int PARAMETER_VALUE_COUNT = 1;
/** The maximum number of bytes this cache should use to store. */
private static final int PARAMETER_CACHE_SIZE = 75 * 1024 * 1024;
private Context context;
private Gson gson;
/** Interface to global information about an application environment. */
private final Context context;
/** Google Json class used for parsing json files. */
private final Gson gson;
/** Cache class used for cache management. */
private DiskLruCache diskCache;
/**
* Constructor of ChapterCache.
* @param context application environment interface.
*/
public ChapterCache(Context context) {
this.context = context;
// Initialize Json handler.
gson = new Gson();
// Try to open cache in default cache directory.
try {
diskCache = DiskLruCache.open(
new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY),
@ -45,43 +69,67 @@ public class ChapterCache {
PARAMETER_CACHE_SIZE
);
} catch (IOException e) {
// Do Nothing.
// Do Nothing. TODO error handling.
}
}
public boolean remove(String file) {
/**
* 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;
}
}
/**
* Returns directory of cache.
* @return directory of cache.
*/
public File getCacheDir() {
return diskCache.getDirectory();
}
public long getRealSize() {
/**
* Returns real size of directory.
* @return real size of directory.
*/
private long getRealSize() {
return DiskUtils.getDirectorySize(getCacheDir());
}
/**
* Returns real size of directory in human readable format.
* @return real size of directory.
*/
public String getReadableSize() {
return Formatter.formatFileSize(context, getRealSize());
}
public void setSize(int value) {
diskCache.setMaxSize(value * 1024 * 1024);
}
/**
* Get page objects from cache.
* @param chapterUrl the url of the chapter.
* @return list of chapter pages.
*/
public Observable<List<Page>> getPageUrlsFromDiskCache(final String chapterUrl) {
return Observable.create(subscriber -> {
try {
// Get list of pages from chapterUrl.
List<Page> pages = getPageUrlsFromDiskCacheImpl(chapterUrl);
// Provides the Observer with a new item to observe.
subscriber.onNext(pages);
// Notify the Observer that finished sending push-based notifications.
subscriber.onCompleted();
} catch (Throwable e) {
subscriber.onError(e);
@ -89,18 +137,31 @@ public class ChapterCache {
});
}
private List<Page> getPageUrlsFromDiskCacheImpl(String chapterUrl) throws IOException {
/**
* Implementation of the getPageUrlsFromDiskCache() function
* @param chapterUrl the url of the chapter
* @return returns list of chapter pages
* @throws IOException does nothing atm
*/
private List<Page> getPageUrlsFromDiskCacheImpl(String chapterUrl) throws IOException /*TODO IOException never thrown*/ {
// Initialize snapshot (a snapshot of the values for an entry).
DiskLruCache.Snapshot snapshot = null;
// Initialize list of pages.
List<Page> pages = null;
try {
// Create md5 key and retrieve snapshot.
String key = DiskUtils.hashKeyForDisk(chapterUrl);
snapshot = diskCache.get(key);
// Convert JSON string to list of objects.
Type collectionType = new TypeToken<List<Page>>() {}.getType();
pages = gson.fromJson(snapshot.getString(0), collectionType);
} catch (IOException e) {
// Do Nothing.
// Do Nothing. //TODO error handling?
} finally {
if (snapshot != null) {
snapshot.close();
@ -109,18 +170,30 @@ public class ChapterCache {
return pages;
}
/**
* Add page urls to disk cache.
* @param chapterUrl the url of the chapter.
* @param pages list of chapter pages.
*/
public void putPageUrlsToDiskCache(final String chapterUrl, final List<Page> pages) {
// Convert list of pages to json string.
String cachedValue = gson.toJson(pages);
// Initialize the editor (edits the values for an entry).
DiskLruCache.Editor editor = null;
// Initialize OutputStream.
OutputStream outputStream = null;
try {
// Get editor from md5 key.
String key = DiskUtils.hashKeyForDisk(chapterUrl);
editor = diskCache.edit(key);
if (editor == null) {
return;
}
// Write chapter urls to cache.
outputStream = new BufferedOutputStream(editor.newOutputStream(0));
outputStream.write(cachedValue.getBytes());
outputStream.flush();
@ -128,7 +201,7 @@ public class ChapterCache {
diskCache.flush();
editor.commit();
} catch (Exception e) {
// Do Nothing.
// Do Nothing. TODO error handling?
} finally {
if (editor != null) {
editor.abortUnlessCommitted();
@ -137,12 +210,17 @@ public class ChapterCache {
try {
outputStream.close();
} catch (IOException ignore) {
// Do Nothing.
// Do Nothing. TODO error handling?
}
}
}
}
/**
* Check if image is in cache.
* @param imageUrl url of image.
* @return true if in cache otherwise false.
*/
public boolean isImageInCache(final String imageUrl) {
try {
return diskCache.get(DiskUtils.hashKeyForDisk(imageUrl)) != null;
@ -152,8 +230,14 @@ public class ChapterCache {
return false;
}
/**
* Get image path from url.
* @param imageUrl url of image.
* @return path of image.
*/
public String getImagePath(final String imageUrl) {
try {
// Get file from md5 key.
String imageName = DiskUtils.hashKeyForDisk(imageUrl) + ".0";
File file = new File(diskCache.getDirectory(), imageName);
return file.getCanonicalPath();
@ -163,17 +247,28 @@ public class ChapterCache {
return null;
}
/**
* Add image to cache
* @param imageUrl url of image.
* @param response http response from page.
* @throws IOException image error.
*/
public void putImageToDiskCache(final String imageUrl, final Response response) throws IOException {
// Initialize editor (edits the values for an entry).
DiskLruCache.Editor editor = null;
// Initialize BufferedSink (used for small writes).
BufferedSink sink = null;
try {
// Get editor from md5 key.
String key = DiskUtils.hashKeyForDisk(imageUrl);
editor = diskCache.edit(key);
if (editor == null) {
throw new IOException("Unable to edit key");
}
// Initialize OutputStream and write image.
OutputStream outputStream = new BufferedOutputStream(editor.newOutputStream(0));
sink = Okio.buffer(Okio.sink(outputStream));
sink.writeAll(response.body().source());

View File

@ -20,33 +20,78 @@ import java.io.OutputStream;
import eu.kanade.tachiyomi.util.DiskUtils;
/**
* Class used to create cover cache
* Makes use of Glide(which can avoid repeating requests) for saving the file.
* It is not necessary to load the images to the cache.
* Names of files are created with the md5 of the thumbnailURL
*/
public class CoverCache {
/**
* Name of cache directory.
*/
private static final String PARAMETER_CACHE_DIRECTORY = "cover_disk_cache";
private Context context;
private File cacheDir;
/**
* Interface to global information about an application environment.
*/
private final Context context;
/**
* Cache class used for cache management.
*/
private final File cacheDir;
/**
* Constructor of CoverCache.
*
* @param context application environment interface.
*/
public CoverCache(Context context) {
this.context = context;
// Get cache directory from parameter.
cacheDir = new File(context.getCacheDir(), PARAMETER_CACHE_DIRECTORY);
// Create cache directory.
createCacheDir();
}
/**
* Check if cache dir exist if not create directory.
*
* @return true if cache dir does exist and is created.
*/
private boolean createCacheDir() {
return !cacheDir.exists() && cacheDir.mkdirs();
}
/**
* Download the cover with Glide (it can avoid repeating requests) and save the file.
*
* @param thumbnailUrl url of thumbnail.
* @param headers headers included in Glide request.
*/
public void save(String thumbnailUrl, LazyHeaders headers) {
save(thumbnailUrl, headers, null);
}
// Download the cover with Glide (it can avoid repeating requests) and save the file on this cache
// Optionally, load the image in the given image view when the resource is ready, if not null
public void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) {
/**
* Download the cover with Glide (it can avoid repeating requests) and save the file.
*
* @param thumbnailUrl url of thumbnail.
* @param headers headers included in Glide request.
* @param imageView imageView where picture should be displayed.
*/
private void save(String thumbnailUrl, LazyHeaders headers, ImageView imageView) {
// Check if url is empty.
if (TextUtils.isEmpty(thumbnailUrl))
// Do not try and create the string. Instead... only try to realize the truth. There is no string.
return;
// Download the cover with Glide and save the file.
GlideUrl url = new GlideUrl(thumbnailUrl, headers);
Glide.with(context)
.load(url)
@ -54,7 +99,10 @@ public class CoverCache {
@Override
public void onResourceReady(File resource, GlideAnimation<? super File> anim) {
try {
add(thumbnailUrl, resource);
// Copy the cover from Glide's cache to local cache.
copyToLocalCache(thumbnailUrl, resource);
// Check if imageView isn't null and show picture in imageView.
if (imageView != null) {
loadFromCache(imageView, resource);
}
@ -65,18 +113,32 @@ public class CoverCache {
});
}
// Copy the cover from Glide's cache to this cache
public void add(String thumbnailUrl, File source) throws IOException {
/**
* Copy the cover from Glide's cache to local cache.
*
* @param thumbnailUrl url of thumbnail.
* @param source the cover image.
* @throws IOException TODO not returned atm?
*/
private void copyToLocalCache(String thumbnailUrl, File source) throws IOException {
// Create cache directory and check if directory exist
createCacheDir();
// Create destination file.
File dest = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl));
// Check if file already exists, if true delete it.
if (dest.exists())
dest.delete();
// Write thumbnail image to file.
InputStream in = new FileInputStream(source);
try {
OutputStream out = new FileOutputStream(dest);
try {
// Transfer bytes from in to out
// Transfer bytes from in to out.
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
@ -90,23 +152,43 @@ public class CoverCache {
}
}
// Get the cover from cache
public File get(String thumbnailUrl) {
/**
* Returns the cover from cache.
*
* @param thumbnailUrl the thumbnail url.
* @return cover image.
*/
private File getCoverFromCache(String thumbnailUrl) {
return new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl));
}
// Delete the cover from cache
public boolean delete(String thumbnailUrl) {
/**
* Delete the cover file from the cache.
*
* @param thumbnailUrl the thumbnail url.
* @return status of deletion.
*/
public boolean deleteCoverFromCache(String thumbnailUrl) {
// Check if url is empty.
if (TextUtils.isEmpty(thumbnailUrl))
return false;
// Remove file.
File file = new File(cacheDir, DiskUtils.hashKeyForDisk(thumbnailUrl));
return file.exists() && file.delete();
}
// Save and load the image from cache
public void saveAndLoadFromCache(ImageView imageView, String thumbnailUrl, LazyHeaders headers) {
File localCover = get(thumbnailUrl);
/**
* 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.
*/
public void saveOrLoadFromCache(ImageView imageView, String thumbnailUrl, LazyHeaders headers) {
// If file exist load it otherwise save it.
File localCover = getCoverFromCache(thumbnailUrl);
if (localCover.exists()) {
loadFromCache(imageView, localCover);
} else {
@ -114,9 +196,17 @@ public class CoverCache {
}
}
// If the image is already in our cache, use it. If not, load it with glide
/**
* 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) {
File localCover = get(thumbnailUrl);
// If localCover exist load it from cache otherwise load it from network.
File localCover = getCoverFromCache(thumbnailUrl);
if (localCover.exists()) {
loadFromCache(imageView, localCover);
} else {
@ -124,8 +214,12 @@ public class CoverCache {
}
}
// Helper method to load the cover from the cache directory into the specified image view
// The file must exist
/**
* Helper method to load the cover from the cache directory into the specified image view.
*
* @param imageView imageView where picture should be displayed.
* @param file file to load. Must exist!.
*/
private void loadFromCache(ImageView imageView, File file) {
Glide.with(context)
.load(file)
@ -134,9 +228,19 @@ public class CoverCache {
.into(imageView);
}
// Helper method to load the cover from network into the specified image view.
// It does NOT save the image in cache
/**
* Helper method to load the cover from network into the specified image view.
* It does NOT save the image in cache!
*
* @param imageView imageView where picture should be displayed.
* @param thumbnailUrl url of thumbnail.
* @param headers headers included in Glide request.
*/
public void loadFromNetwork(ImageView imageView, String thumbnailUrl, LazyHeaders headers) {
// Check if url is empty.
if (TextUtils.isEmpty(thumbnailUrl))
return;
GlideUrl url = new GlideUrl(thumbnailUrl, headers);
Glide.with(context)
.load(url)

View File

@ -7,8 +7,16 @@ import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.module.GlideModule;
/**
* Class used to update Glide module settings
*/
public class CoverGlideModule implements GlideModule {
/**
* Bitmaps decoded from most image formats (other than GIFs with hidden configs), will be decoded with the
* ARGB_8888 config.
*/
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
@ -16,6 +24,6 @@ public class CoverGlideModule implements GlideModule {
@Override
public void registerComponents(Context context, Glide glide) {
// Nothing to see here!
}
}

View File

@ -44,7 +44,7 @@ public class LibraryHolder extends FlexibleViewHolder {
private void loadCover(Manga manga, Source source, CoverCache coverCache) {
if (manga.thumbnail_url != null) {
coverCache.saveAndLoadFromCache(thumbnail, manga.thumbnail_url, source.getGlideHeaders());
coverCache.saveOrLoadFromCache(thumbnail, manga.thumbnail_url, source.getGlideHeaders());
} else {
thumbnail.setImageResource(android.R.color.transparent);
}

View File

@ -88,7 +88,7 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
LazyHeaders headers = getPresenter().source.getGlideHeaders();
if (manga.thumbnail_url != null && cover.getDrawable() == null) {
if (manga.favorite) {
coverCache.saveAndLoadFromCache(cover, manga.thumbnail_url, headers);
coverCache.saveOrLoadFromCache(cover, manga.thumbnail_url, headers);
} else {
coverCache.loadFromNetwork(cover, manga.thumbnail_url, headers);
}

View File

@ -19,17 +19,18 @@ import rx.schedulers.Schedulers;
public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
@Inject DatabaseHelper db;
@Inject SourceManager sourceManager;
@Inject CoverCache coverCache;
private Manga manga;
protected Source source;
private int count = -1;
private static final int GET_MANGA = 1;
private static final int GET_CHAPTER_COUNT = 2;
private static final int FETCH_MANGA_INFO = 3;
protected Source source;
@Inject
DatabaseHelper db;
@Inject
SourceManager sourceManager;
@Inject
CoverCache coverCache;
private Manga manga;
private int count = -1;
@Override
protected void onCreate(Bundle savedState) {
@ -111,7 +112,7 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
if (isFavorite) {
coverCache.save(manga.thumbnail_url, source.getGlideHeaders());
} else {
coverCache.delete(manga.thumbnail_url);
coverCache.deleteCoverFromCache(manga.thumbnail_url);
}
}

View File

@ -71,7 +71,7 @@ public class SettingsAdvancedFragment extends SettingsNestedFragment {
subscriptions.add(Observable.defer(() -> Observable.from(files))
.concatMap(file -> {
if (chapterCache.remove(file.getName())) {
if (chapterCache.removeFileFromCache(file.getName())) {
deletedFiles.incrementAndGet();
}
return Observable.just(file);