added image cache for emoji images
This commit is contained in:
parent
96f6aba71e
commit
af381a8feb
|
@ -11,11 +11,9 @@ import org.nuclearfog.twidda.backend.api.Connection;
|
|||
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionManager;
|
||||
import org.nuclearfog.twidda.backend.helper.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.utils.ImageCache;
|
||||
import org.nuclearfog.twidda.model.Emoji;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
@ -27,18 +25,15 @@ import java.util.TreeMap;
|
|||
*/
|
||||
public class EmojiLoader extends AsyncExecutor<EmojiLoader.EmojiParam, EmojiLoader.EmojiResult> {
|
||||
|
||||
private static final String FOLDER = "emojis";
|
||||
|
||||
private File imageFolder;
|
||||
private Connection connection;
|
||||
private ImageCache cache;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public EmojiLoader(Context context) {
|
||||
connection = ConnectionManager.getDefaultConnection(context);
|
||||
imageFolder = new File(context.getExternalCacheDir(), FOLDER);
|
||||
imageFolder.mkdirs();
|
||||
cache = ImageCache.getInstance(context);
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,37 +41,17 @@ public class EmojiLoader extends AsyncExecutor<EmojiLoader.EmojiParam, EmojiLoad
|
|||
@Override
|
||||
protected EmojiResult doInBackground(@NonNull EmojiParam param) {
|
||||
try {
|
||||
Map<String, File> files = new TreeMap<>();
|
||||
Map<String, Bitmap> result = new TreeMap<>();
|
||||
// cache all local image files first
|
||||
File[] imageFiles = imageFolder.listFiles();
|
||||
if (imageFiles != null) {
|
||||
for (File file : imageFiles) {
|
||||
files.put(file.getName(), file);
|
||||
}
|
||||
}
|
||||
for (Emoji emoji : param.emojis) {
|
||||
File file = files.get(emoji.getCode());
|
||||
if (file == null) {
|
||||
// download image to cache
|
||||
Bitmap icon = cache.getImage(emoji.getCode());
|
||||
if (icon == null) {
|
||||
MediaStatus media = connection.downloadImage(emoji.getUrl());
|
||||
InputStream input = media.getStream();
|
||||
file = new File(imageFolder, emoji.getCode());
|
||||
file.createNewFile();
|
||||
FileOutputStream output = new FileOutputStream(file);
|
||||
Bitmap icon = BitmapFactory.decodeStream(input);
|
||||
icon.compress(Bitmap.CompressFormat.PNG, 1, output);
|
||||
// resize image
|
||||
icon = Bitmap.createScaledBitmap(icon, icon.getWidth() / icon.getHeight() * param.size, param.size, false);
|
||||
result.put(emoji.getCode(), icon);
|
||||
} else {
|
||||
// load image from cache
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
Bitmap icon = BitmapFactory.decodeStream(inputStream);
|
||||
// resize image
|
||||
icon = Bitmap.createScaledBitmap(icon, icon.getWidth() / icon.getHeight() * param.size, param.size, false);
|
||||
result.put(emoji.getCode(), icon);
|
||||
icon = BitmapFactory.decodeStream(input);
|
||||
cache.putImage(emoji.getCode(), icon);
|
||||
}
|
||||
icon = Bitmap.createScaledBitmap(icon, icon.getWidth() / icon.getHeight() * param.size, param.size, false);
|
||||
result.put(emoji.getCode(), icon);
|
||||
}
|
||||
return new EmojiResult(result, null);
|
||||
} catch (ConnectionException exception) {
|
||||
|
@ -90,6 +65,7 @@ public class EmojiLoader extends AsyncExecutor<EmojiLoader.EmojiParam, EmojiLoad
|
|||
*
|
||||
*/
|
||||
public static class EmojiParam {
|
||||
|
||||
Emoji[] emojis;
|
||||
int size;
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
package org.nuclearfog.twidda.backend.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.util.LruCache;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* This class represents an image cache for emoji icons
|
||||
* There are both, image cache and file cache. If image doesn't exist in the cache, the file cache is used to search for the file.
|
||||
* A new image will be cached and saved as file to the local cache storage.
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class ImageCache {
|
||||
|
||||
/**
|
||||
* size of the lru cache (max entry count)
|
||||
*/
|
||||
private static final int SIZE = 64;
|
||||
|
||||
/**
|
||||
* folder name of the local cache
|
||||
*/
|
||||
private static final String FOLDER = "images";
|
||||
|
||||
private static ImageCache instance;
|
||||
|
||||
@Nullable
|
||||
private File imageFolder;
|
||||
|
||||
private LruCache<String, Bitmap> cache;
|
||||
|
||||
private Map<String, File> files;
|
||||
|
||||
|
||||
/**
|
||||
* @param context context used to determine cache folder path
|
||||
*/
|
||||
private ImageCache(Context context) {
|
||||
files = new TreeMap<>();
|
||||
cache = new LruCache<>(SIZE);
|
||||
try {
|
||||
imageFolder = new File(context.getExternalCacheDir(), FOLDER);
|
||||
imageFolder.mkdirs();
|
||||
File[] imageFiles = imageFolder.listFiles();
|
||||
if (imageFiles != null) {
|
||||
for (File file : imageFiles) {
|
||||
files.put(file.getName(), file);
|
||||
}
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* put image to cache and save as file if not exists
|
||||
*
|
||||
* @param key key of the image (tag)
|
||||
* @param image image bitmap
|
||||
*/
|
||||
public void putImage(String key, Bitmap image) {
|
||||
cache.put(key, image);
|
||||
if (imageFolder != null && !files.containsKey(key)) {
|
||||
try {
|
||||
File file = new File(imageFolder, key);
|
||||
file.createNewFile();
|
||||
FileOutputStream output = new FileOutputStream(file);
|
||||
image.compress(Bitmap.CompressFormat.PNG, 1, output);
|
||||
files.put(key, file);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get image from cache or file
|
||||
*
|
||||
* @param key key of the image (tag)
|
||||
* @return image bitmap or null if not found
|
||||
*/
|
||||
@Nullable
|
||||
public Bitmap getImage(String key) {
|
||||
Bitmap result = cache.get(key);
|
||||
if (result == null) {
|
||||
File file = files.get(key);
|
||||
if (file != null) {
|
||||
try {
|
||||
FileInputStream inputStream = new FileInputStream(file);
|
||||
result = BitmapFactory.decodeStream(inputStream);
|
||||
cache.put(key, result);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* create singleton instance of this class
|
||||
*
|
||||
* @return singleton instance of this class
|
||||
*/
|
||||
public static ImageCache getInstance(Context context) {
|
||||
if (instance == null)
|
||||
instance = new ImageCache(context);
|
||||
return instance;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue