Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6_1_X][TIMOB-14742] Android: Fixed window/view "backgroundImage" assignment where it loads the same image 4 times. #9032

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,16 @@ public static void setTextViewDIPPadding(TextView textView, int horizontalPaddin
}

public static Drawable buildBackgroundDrawable(String color, String image, boolean tileImage, Drawable gradientDrawable)
{
Drawable imageDrawable = null;
if (image != null) {
TiFileHelper tfh = TiFileHelper.getInstance();
imageDrawable = tfh.loadDrawable(image, false, true, false);
}
return buildBackgroundDrawable(color, imageDrawable, tileImage, gradientDrawable);
}

public static Drawable buildBackgroundDrawable(String color, Drawable imageDrawable, boolean tileImage, Drawable gradientDrawable)
{
// Create an array of the layers that will compose this background.
// Note that the order in which the layers is important to get the
Expand All @@ -587,23 +597,17 @@ public static Drawable buildBackgroundDrawable(String color, String image, boole
layers.add(gradientDrawable);
}

Drawable imageDrawable = null;
if (image != null) {
TiFileHelper tfh = TiFileHelper.getInstance();
imageDrawable = tfh.loadDrawable(image, false, true, false);

if (tileImage) {
if (imageDrawable instanceof BitmapDrawable) {
BitmapDrawable tiledBackground = (BitmapDrawable) imageDrawable;
tiledBackground.setTileModeX(Shader.TileMode.REPEAT);
tiledBackground.setTileModeY(Shader.TileMode.REPEAT);
imageDrawable = tiledBackground;
}
if (tileImage) {
if (imageDrawable instanceof BitmapDrawable) {
BitmapDrawable tiledBackground = (BitmapDrawable) imageDrawable;
tiledBackground.setTileModeX(Shader.TileMode.REPEAT);
tiledBackground.setTileModeY(Shader.TileMode.REPEAT);
imageDrawable = tiledBackground;
}
}

if (imageDrawable != null) {
layers.add(imageDrawable);
}
if (imageDrawable != null) {
layers.add(imageDrawable);
}

return new LayerDrawable(layers.toArray(new Drawable[layers.size()]));
Expand Down Expand Up @@ -642,29 +646,81 @@ public static StateListDrawable buildBackgroundDrawable(
String focusedColor,
Drawable gradientDrawable)
{
StateListDrawable sld = new StateListDrawable();
// Anonymous class used by this method to load image drawables.
// Supports drawable caching to prevent the same image file from being decoded twice.
class ImageDrawableLoader {
/** Hash table used to cache loaded drawables by their image file paths. */
private HashMap<String, Drawable> imagePathDrawableMap;

/** Creates a new image drawable loader. */
public ImageDrawableLoader() {
this.imagePathDrawableMap = new HashMap<String, Drawable>(4);
}

/**
* Loads the given image and returns it's decode bitmap wrapped in a drawable.
* @param filePath Path or URL to the image file to be loaded. Can be null.
* @return Returns a drawble object used to draw the give image file.
* <p>
* Returns null if failed to load the image or if given a null argument.
*/
Drawable load(String filePath) {
// Validate image file path.
if ((filePath == null) || (filePath.length() <= 0)) {
return null;
}

// Check if the given image has already been loaded before.
Drawable drawable = this.imagePathDrawableMap.get(filePath);
if (drawable == null) {
// Image has not been loaded before. Load it as a drawable now.
TiFileHelper fileHelper = TiFileHelper.getInstance();
drawable = fileHelper.loadDrawable(filePath, false, true, false);
if (drawable != null) {
// Image was successfully loaded. Add it to the cache.
this.imagePathDrawableMap.put(filePath, drawable);
}
}
else {
// Given image was loaded before. Create a new drawable using the last cached version.
// Note: The new drawable will share the cached drawable's bitmap, which avoids decoding the
// same image twice. This is a huge performance and memory optimization.
Resources resources = TiApplication.getInstance().getResources();
drawable = drawable.getConstantState().newDrawable(resources).mutate();
}
return drawable;
}
}

// Load the given images to drawables using the anonymous class above.
// Note: This is an optimization. Image loader can share the same bitmap between multiple drawables.
ImageDrawableLoader imageDrawableLoader = new ImageDrawableLoader();
Drawable mainImageDrawable = imageDrawableLoader.load(image);
Drawable selectedImageDrawable = imageDrawableLoader.load(selectedImage);
Drawable disabledImageDrawable = imageDrawableLoader.load(disabledImage);
Drawable focusedImageDrawable = imageDrawableLoader.load(focusedImage);

Drawable bgSelectedDrawable = buildBackgroundDrawable(selectedColor, selectedImage, tileImage, gradientDrawable);
// Create the layered drawable objects for the the UI object's different states.
StateListDrawable sld = new StateListDrawable();
Drawable bgSelectedDrawable = buildBackgroundDrawable(selectedColor, selectedImageDrawable, tileImage, gradientDrawable);
if (bgSelectedDrawable != null) {
sld.addState(BACKGROUND_SELECTED_STATE, bgSelectedDrawable);
}

Drawable bgFocusedDrawable = buildBackgroundDrawable(focusedColor, focusedImage, tileImage, gradientDrawable);
Drawable bgFocusedDrawable = buildBackgroundDrawable(focusedColor, focusedImageDrawable, tileImage, gradientDrawable);
if (bgFocusedDrawable != null) {
sld.addState(BACKGROUND_FOCUSED_STATE, bgFocusedDrawable);
}

Drawable bgDisabledDrawable = buildBackgroundDrawable(disabledColor, disabledImage, tileImage, gradientDrawable);
Drawable bgDisabledDrawable = buildBackgroundDrawable(disabledColor, disabledImageDrawable, tileImage, gradientDrawable);
if (bgDisabledDrawable != null) {
sld.addState(BACKGROUND_DISABLED_STATE, bgDisabledDrawable);
}

Drawable bgDrawable = buildBackgroundDrawable(color, image, tileImage, gradientDrawable);
Drawable bgDrawable = buildBackgroundDrawable(color, mainImageDrawable, tileImage, gradientDrawable);
if (bgDrawable != null) {
sld.addState(BACKGROUND_DEFAULT_STATE_1, bgDrawable);
sld.addState(BACKGROUND_DEFAULT_STATE_2, bgDrawable);
}

// Return the requested multi-state drawable.
return sld;
}

Expand Down