I'm building an app that has plenty of screens. most of the screens have a View at the top with a background color.
I often change that color using view.setBackgroundColor(color)
Here comes the weird thing: sometimes after setting the color of one view, say to #f14fb7 , when navigating in the app, other views' backgrounds are set to that color without me wanting them to. It sometimes even happens to views I had not set an id for, so there is no way setBackgroundColor was called on those views.
This happens rarely and is not consistant to any flow I tried.
When I kill the app and restart it, everything works as it should.
My only guess is some king of memory leak, but I hope there is a simpler explanation.
Can anyone think of some reason for this to happen?
*It happens on my Galaxy S3.
Without the code it's not easy... but I guess you are reusing the same ColorDrawable
on multiple views and if you take a look at View.setBackgroundColor()
source code :
public void setBackgroundColor(int color) {
if (mBGDrawable instanceof ColorDrawable) {
((ColorDrawable) mBGDrawable).setColor(color);
} else {
setBackgroundDrawable(new ColorDrawable(color));
}
}
You can see that it change the color of the ColorDrawable
and don't create a new one each time. I'm pretty sure this is why you have this strange behavior.
EDIT
When you set the initial background color in xml with android:background
you are doing this (according android doc):
Set the background to a given resource. The resource should refer to a Drawable object
According my understanding it will set the field View.mBGDrawable
during the inflate. I suggest you to use View.setBackgoundDrawable(new ColorDrawable(the_color_int_code)))
instead of setBackgroung(the_color_int_code)
. It should solve your issue.
This usually happens if you have a view whose color is set in xml ex:
android:background="@color/cyan"
Now this internally creates a new ColorDrawable
- lets call it conceptual_drawable_cyan
inside that view's class. Now when same view is assigned a different color programmatically using:
view.setBackgroundColor(newColor);
Internally this view instead of creating a different drawable it sets this newColor
to drawable_cyan
. Hence from this point onwards if you anywhere use
android:background="@color/cyan"
the view would actually use conceptual_drawable_cyan
with newColor
.
Solution:
Instead of using setBackgroundColor
to set color programmatically, use:
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.setBackground(new ColorDrawable(newColor));
} else {
view.setBackgroundDrawable(new ColorDrawable(newColor));
}
Create the "colors.xml" file under the "values" folder. Example:
<?xml version="1.0" encoding="utf-8"?>
<resources><color name="pink">#f14fb7</color></resources>
Use view.setBackgroundResource(R.color.pink);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With