Jackd
Jackd

Reputation: 131

Android colors, fastest?

What is faster android ?

Color.rgb(184, 134, 011);

or

Color.parseColor("#234181");

Or somethin else ?

Answer: The fastest seems to be:

int mycolor = 0xff234181;

Thanks to samgak and KenWolf.

However now I wonder how common functions handle it, here is the source of 2 View setbackgroundcolor() and TextView settextcolor() and (some) following function:

public void setBackgroundColor(int color) {
    if (mBackground instanceof ColorDrawable) {
        ((ColorDrawable) mBackground.mutate()).setColor(color);
        computeOpaqueFlags();
        mBackgroundResource = 0;
    } else {
        setBackground(new ColorDrawable(color));
    }
}

public void setBackground(Drawable background) {
    //noinspection deprecation
    setBackgroundDrawable(background);
}

public void setBackgroundDrawable(Drawable background) {
    computeOpaqueFlags();

    if (background == mBackground) {
        return;
    }

    boolean requestLayout = false;

    mBackgroundResource = 0;

    /*
     * Regardless of whether we're setting a new background or not, we want
     * to clear the previous drawable.
     */
    if (mBackground != null) {
        mBackground.setCallback(null);
        unscheduleDrawable(mBackground);
    }

    if (background != null) {
        Rect padding = sThreadLocal.get();
        if (padding == null) {
            padding = new Rect();
            sThreadLocal.set(padding);
        }
        resetResolvedDrawables();
        background.setLayoutDirection(getLayoutDirection());
        if (background.getPadding(padding)) {
            resetResolvedPadding();
            switch (background.getLayoutDirection()) {
                case LAYOUT_DIRECTION_RTL:
                    mUserPaddingLeftInitial = padding.right;
                    mUserPaddingRightInitial = padding.left;
                    internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
                    break;
                case LAYOUT_DIRECTION_LTR:
                default:
                    mUserPaddingLeftInitial = padding.left;
                    mUserPaddingRightInitial = padding.right;
                    internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
            }
            mLeftPaddingDefined = false;
            mRightPaddingDefined = false;
        }

        // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
        // if it has a different minimum size, we should layout again
        if (mBackground == null
                || mBackground.getMinimumHeight() != background.getMinimumHeight()
                || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
            requestLayout = true;
        }

        background.setCallback(this);
        if (background.isStateful()) {
            background.setState(getDrawableState());
        }
        background.setVisible(getVisibility() == VISIBLE, false);
        mBackground = background;

        applyBackgroundTint();

        if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
            mPrivateFlags &= ~PFLAG_SKIP_DRAW;
            mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
            requestLayout = true;
        }
    } else {
        /* Remove the background */
        mBackground = null;

        if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
            /*
             * This view ONLY drew the background before and we're removing
             * the background, so now it won't draw anything
             * (hence we SKIP_DRAW)
             */
            mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
            mPrivateFlags |= PFLAG_SKIP_DRAW;
        }

        /*
         * When the background is set, we try to apply its padding to this
         * View. When the background is removed, we don't touch this View's
         * padding. This is noted in the Javadocs. Hence, we don't need to
         * requestLayout(), the invalidate() below is sufficient.
         */

        // The old background's minimum size could have affected this
        // View's layout, so let's requestLayout
        requestLayout = true;
    }

    computeOpaqueFlags();

    if (requestLayout) {
        requestLayout();
    }

    mBackgroundSizeChanged = true;
    invalidate(true);
}

and

public void setTextColor(int color) {
mTextColor = ColorStateList.valueOf(color);
    updateTextColors();
}

public void setTextColor(ColorStateList colors) {
    if (colors == null) {
        throw new NullPointerException();
    }

    mTextColor = colors;
    updateTextColors();
}

private void updateTextColors() {
    boolean inval = false;
    int color = mTextColor.getColorForState(getDrawableState(), 0);
    if (color != mCurTextColor) {
        mCurTextColor = color;
        inval = true;
    }
    if (mLinkTextColor != null) {
        color = mLinkTextColor.getColorForState(getDrawableState(), 0);
        if (color != mTextPaint.linkColor) {
            mTextPaint.linkColor = color;
            inval = true;
        }
    }
    if (mHintTextColor != null) {
        color = mHintTextColor.getColorForState(getDrawableState(), 0);
        if (color != mCurHintTextColor && mText.length() == 0) {
            mCurHintTextColor = color;
            inval = true;
        }
    }
    if (inval) {
        // Text needs to be redrawn with the new color
        if (mEditor != null) mEditor.invalidateTextDisplayList();
        invalidate();
    }
}

setTextColor() ends with an invalidate().

setBackgroundColor() ends with an invalidate() ? or .mutate()).setColor(color) ? or applyBackgroundTint() ?

Upvotes: 1

Views: 990

Answers (3)

Varundroid
Varundroid

Reputation: 9234

Definitely the Color.rgb(184, 134, 011) is faster than Colors.parseColor(). That's because now there is no need to convert the hex into rgb while you are providing rgb upfront but still below is the recommended way of using colors in Android -

Add the following in your colors.xml -

<color name="my_color">#234181 </color>

In case, if colors.xml doesn't exist inside res/values then create it first inside res/values folder and add the above line afterwards.

Then you can get the color in your code by doing something like this -

Inside your Activity and Fragment -

getResources().getColor(R.color.my_color);

In any other class that has access to Activity or Application Context -

context.getResources().getColor(R.color.my_color);

Hope it would help.

Upvotes: 0

samgak
samgak

Reputation: 24427

Or somethin else ?

It depends on what you are passing in. If you are passing hard-coded values into the functions, and assigning the return value to an integer variable, then the fastest method is to not call any function at all but just assign a hex value representing the color to the integer variable directly.

for e.g:

int colorValue = Color.rgb(184, 134, 011);

can be replaced with

int colorValue = 0xffb8860b;

which is what would have been returned from Color.rgb() anyway.

Likewise

int colorValue = Color.parseColor("#234181");

can be replaced with

int colorValue = 0xff234181;

This sacrifices readability and convenience for (probably negligible) speed improvement, but you could make it more readable by declaring the hex color values as static final int constants with meaningful color names.

Upvotes: 2

Ken Wolf
Ken Wolf

Reputation: 23279

https://github.com/android/platform_frameworks_base/blob/master/graphics/java/android/graphics/Color.java

public static int rgb(int red, int green, int blue) {
    return (0xFF << 24) | (red << 16) | (green << 8) | blue;
}

vs

public static int parseColor(String colorString) {
    if (colorString.charAt(0) == '#') {
        // Use a long to avoid rollovers on #ffXXXXXX
        long color = Long.parseLong(colorString.substring(1), 16);
        if (colorString.length() == 7) {
            // Set the alpha value
            color |= 0x00000000ff000000;
        } else if (colorString.length() != 9) {
            throw new IllegalArgumentException("Unknown color");
        }
        return (int)color;
    } else {
        Integer color = sColorNameMap.get(colorString.toLowerCase(Locale.ROOT));
        if (color != null) {
            return color;
        }
    }
    throw new IllegalArgumentException("Unknown color");
}

I haven't measured but I would guess

Color.rgb(184, 134, 011));

is faster as it uses simple bitshifting and has to deal with a smaller input set.

I would imagine in practice the difference is negligible at best.

Upvotes: 3

Related Questions