am 10e2700d: Merge "Ensure calling mutate() on DrawableContainer creates a new state" into lmp-mr1-dev

* commit '10e2700d50f68a4943ee2d7fe0804db73dc76bff':
  Ensure calling mutate() on DrawableContainer creates a new state
This commit is contained in:
Alan Viverette
2014-11-25 23:50:54 +00:00
committed by Android Git Automerger
5 changed files with 81 additions and 37 deletions

View File

@@ -527,14 +527,18 @@ public class AnimatedStateListDrawable extends StateListDrawable {
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
final AnimatedStateListState newState = new AnimatedStateListState(mState, this, null);
setConstantState(newState);
mState.mutate();
mMutated = true;
}
return this;
}
@Override
AnimatedStateListState cloneConstantState() {
return new AnimatedStateListState(mState, this, null);
}
/**
* @hide
*/
@@ -553,23 +557,29 @@ public class AnimatedStateListDrawable extends StateListDrawable {
int[] mAnimThemeAttrs;
final LongSparseLongArray mTransitions;
final SparseIntArray mStateIds;
LongSparseLongArray mTransitions;
SparseIntArray mStateIds;
AnimatedStateListState(@Nullable AnimatedStateListState orig,
@NonNull AnimatedStateListDrawable owner, @Nullable Resources res) {
super(orig, owner, res);
if (orig != null) {
// Perform a shallow copy and rely on mutate() to deep-copy.
mAnimThemeAttrs = orig.mAnimThemeAttrs;
mTransitions = orig.mTransitions.clone();
mStateIds = orig.mStateIds.clone();
mTransitions = orig.mTransitions;
mStateIds = orig.mStateIds;
} else {
mTransitions = new LongSparseLongArray();
mStateIds = new SparseIntArray();
}
}
private void mutate() {
mTransitions = mTransitions.clone();
mStateIds = mStateIds.clone();
}
int addTransition(int fromId, int toId, @NonNull Drawable anim, boolean reversible) {
final int pos = super.addChild(anim);
final long keyFromTo = generateTransitionKey(fromId, toId);
@@ -641,15 +651,18 @@ public class AnimatedStateListDrawable extends StateListDrawable {
}
}
void setConstantState(@NonNull AnimatedStateListState state) {
protected void setConstantState(@NonNull DrawableContainerState state) {
super.setConstantState(state);
mState = state;
if (state instanceof AnimatedStateListState) {
mState = (AnimatedStateListState) state;
}
}
private AnimatedStateListDrawable(@Nullable AnimatedStateListState state, @Nullable Resources res) {
super(null);
// Every animated state list drawable has its own constant state.
final AnimatedStateListState newState = new AnimatedStateListState(state, this, res);
setConstantState(newState);
onStateChange(getState());

View File

@@ -342,12 +342,17 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
mAnimationState.mDurations = mAnimationState.mDurations.clone();
mAnimationState.mutate();
mMutated = true;
}
return this;
}
@Override
AnimationState cloneConstantState() {
return new AnimationState(mAnimationState, this, null);
}
/**
* @hide
*/
@@ -373,6 +378,10 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
}
}
private void mutate() {
mDurations = mDurations.clone();
}
@Override
public Drawable newDrawable() {
return new AnimationDrawable(this, null);

View File

@@ -536,7 +536,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
}
if (schedule && animating) {
scheduleSelf(mAnimationRunnable, now + 1000/60);
scheduleSelf(mAnimationRunnable, now + 1000 / 60);
}
}
@@ -567,12 +567,23 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
mDrawableContainerState = cloneConstantState();
mDrawableContainerState.mutate();
mMutated = true;
}
return this;
}
/**
* Returns a shallow copy of the container's constant state to be used as
* the base state for {@link #mutate()}.
*
* @return a shallow copy of the constant state
*/
DrawableContainerState cloneConstantState() {
return mDrawableContainerState;
}
/**
* @hide
*/
@@ -833,7 +844,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
return false;
}
final void mutate() {
private void mutate() {
// No need to call createAllFutures, since future drawables will
// mutate when they are prepared.
final int N = mNumChildren;

View File

@@ -146,13 +146,17 @@ public class LevelListDrawable extends DrawableContainer {
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
mLevelListState.mLows = mLevelListState.mLows.clone();
mLevelListState.mHighs = mLevelListState.mHighs.clone();
mLevelListState.mutate();
mMutated = true;
}
return this;
}
@Override
LevelListState cloneConstantState() {
return new LevelListState(mLevelListState, this, null);
}
/**
* @hide
*/
@@ -169,6 +173,7 @@ public class LevelListDrawable extends DrawableContainer {
super(orig, owner, res);
if (orig != null) {
// Perform a shallow copy and rely on mutate() to deep-copy.
mLows = orig.mLows;
mHighs = orig.mHighs;
} else {
@@ -177,6 +182,11 @@ public class LevelListDrawable extends DrawableContainer {
}
}
private void mutate() {
mLows = mLows.clone();
mHighs = mHighs.clone();
}
public void addLevel(int low, int high, Drawable drawable) {
int pos = addChild(drawable);
mLows[pos] = low;

View File

@@ -24,6 +24,8 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.Arrays;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
@@ -288,20 +290,17 @@ public class StateListDrawable extends DrawableContainer {
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
final int[][] sets = mStateListState.mStateSets;
final int count = sets.length;
mStateListState.mStateSets = new int[count][];
for (int i = 0; i < count; i++) {
final int[] set = sets[i];
if (set != null) {
mStateListState.mStateSets[i] = set.clone();
}
}
mStateListState.mutate();
mMutated = true;
}
return this;
}
@Override
StateListState cloneConstantState() {
return new StateListState(mStateListState, this, null);
}
/**
* @hide
*/
@@ -328,25 +327,24 @@ public class StateListDrawable extends DrawableContainer {
super(orig, owner, res);
if (orig != null) {
// Perform a deep copy.
final int[][] sets = orig.mStateSets;
final int count = sets.length;
mStateSets = new int[count][];
for (int i = 0; i < count; i++) {
final int[] set = sets[i];
if (set != null) {
mStateSets[i] = set.clone();
}
}
// Perform a shallow copy and rely on mutate() to deep-copy.
mThemeAttrs = orig.mThemeAttrs;
mStateSets = Arrays.copyOf(orig.mStateSets, orig.mStateSets.length);
mStateSets = orig.mStateSets;
} else {
mThemeAttrs = null;
mStateSets = new int[getCapacity()][];
}
}
private void mutate() {
mThemeAttrs = mThemeAttrs != null ? mThemeAttrs.clone() : null;
final int[][] stateSets = new int[mStateSets.length][];
for (int i = mStateSets.length - 1; i >= 0; i--) {
stateSets[i] = mStateSets[i] != null ? mStateSets[i].clone() : null;
}
}
int addStateSet(int[] stateSet, Drawable drawable) {
final int pos = addChild(drawable);
mStateSets[pos] = stateSet;
@@ -395,13 +393,16 @@ public class StateListDrawable extends DrawableContainer {
onStateChange(getState());
}
void setConstantState(StateListState state) {
protected void setConstantState(@NonNull DrawableContainerState state) {
super.setConstantState(state);
mStateListState = state;
if (state instanceof StateListState) {
mStateListState = (StateListState) state;
}
}
private StateListDrawable(StateListState state, Resources res) {
// Every state list drawable has its own constant state.
final StateListState newState = new StateListState(state, this, res);
setConstantState(newState);
onStateChange(getState());
@@ -411,7 +412,7 @@ public class StateListDrawable extends DrawableContainer {
* This constructor exists so subclasses can avoid calling the default
* constructor and setting up a StateListDrawable-specific constant state.
*/
StateListDrawable(StateListState state) {
StateListDrawable(@Nullable StateListState state) {
if (state != null) {
setConstantState(state);
}