Let me start by saying that I am very happy with this code. I want to share it with other people because I think they will find it helpful, but I want to make sure I did everything in good form before I do so.
The code allows users to easily manage their image memory. The class handles all of your images, which means no image will be unnecessarily created twice. Each time a new class is created the user can just call recycle()
to recycle all the images that were used in the previous class and load all the images needed in the class. Images can be added to this custom class by calling loadImages()
and the user can redefine and remove items by calling recycle()
with only the images they want to keep (they can also add image here). They can also define images to be scaled custom.
All of that can be done by properly using the onResume
and OnPause
methods, but this class greatly simplifies it and neatens the code in my opinion. BUT this class can do something that can't be done with the onPause
and onResume
methods. When loading a new classes images, the images used in the previous classes don't need to be reloaded. Depending on the application the time this saves varies. In my application it saves a visible amount of time due to the large number of duplicate images used in different classes.
What do you think? How could this be improve? Is it worth sharing?
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.DisplayMetrics;
import android.view.View;
public class Images {
// Image Holder
private ArrayList<Bitmap> images;
// Image Names
private ArrayList<String> imageNames;
// Images that need custom scaling
private ArrayList<String> customScale;
// Options, used for proper scaling
BitmapFactory.Options options;
private Images() {
// init
images = new ArrayList<Bitmap>();
imageNames = new ArrayList<String>();
options = new BitmapFactory.Options();
customScale = new ArrayList<String>();
// Assigns image names
nameImages();
// Set which images should be custom scaled
setCustomScales();
// by default images are null
for (int i = 0; i < imageNames.size(); i++)
images.add(null);
}
//singleton stuff
private static class Holder {
static final Images INSTANCE = new Images();
}
public static Images getInstance() {
return Holder.INSTANCE;
}
// recycle all images not in use
public void recycle(ArrayList<String> imagesInUse, View sv, double scale, DisplayMetrics dm) {
for (int i = 0; i < imageNames.size(); i++)
if (!imagesInUse.contains(imageNames.get(i)))
images.get(i).recycle();
loadImages(imagesInUse, sv, scale, dm);
}
// load all needed images
public void loadImages(ArrayList<String> imageName, View sv, double scale, DisplayMetrics dm) {
Context context = sv.getContext();
for (int ii = 0; ii < imageName.size(); ii++) {
for (int i = 0; i < imageNames.size(); i++) {
if (imageNames.get(i).equals(imageName.get(ii))) {
int resID = sv.getResources().getIdentifier(imageName.get(ii), "drawable", context.getPackageName());
if (customScale.contains(imageName.get(ii))) {
images.set(i, BitmapFactory.decodeResource(sv.getResources(), resID));
images.set(i, customScaleImage(imageName.get(ii), i, dm));
}
else {
if (scale < .5) {
options.inSampleSize = 2;
images.set(i, BitmapFactory.decodeResource(sv.getResources(), resID, options));
if (scale != .5)
images.set(i, Bitmap.createScaledBitmap(images.get(i), (int) (images.get(i).getWidth() * 2 * scale + .5), (int) (images.get(i).getHeight() * 2 * scale + .5), true));
} else {
images.set(i, BitmapFactory.decodeResource(sv.getResources(), resID));
images.set(i, Bitmap.createScaledBitmap(images.get(i), (int) (images.get(i).getWidth() * scale + .5), (int) (images.get(i).getHeight() * scale + .5), true));
}
}
}
}
}
}
// returns bitmap with name of 'imageName'
public Bitmap getImage(String imageName) {
for (int i = 0; i < imageNames.size(); i++) {
if (imageNames.get(i).equals(imageName))
return images.get(i);
}
System.err.println("NO IMAGE OF NAME '" + imageName + "' FOUND!");
return null;
}
// set how you want to custom scale your custom scale images
private Bitmap customScaleImage(String nameOfImage, int index, DisplayMetrics dm) {
if (nameOfImage.equals("example"))
return Bitmap.createScaledBitmap(images.get(index), dm.widthPixels, dm.heightPixels, true);
System.err.println("CUSTOM SCALE NOT SET FOR " + nameOfImage);
return null;
}
// name all images
private void nameImages() {
imageNames.add("example");
}
// Add all custom scale images
private void setCustomScales(){
customScale.add("example");
}
}