android ValueAnimator性能问题,一些工作后得到滞后

时间:2015-12-18 15:58:25

标签: android performance memory-leaks lag objectanimator

我正在开发用户“eluleci”(https://gist.github.com/eluleci/6e0d02c766b27f6a5253)代码     对于preLilop来说,这是涟漪。

好吧,它扩展了Button类来做到这一点,     当我们的布局中有一个按钮时,所有东西都很好用,动画工作顺利,     但是当我们添加多个按钮(如5个按钮)时,通过触摸它们,按钮上的动画会变得滞后而不平滑!!

我无法理解这是什么问题?记忆问题?我该如何解决?谁能知道问题出在哪里?     谢谢你的关注

这是我的代码:

public class MehDiRippleButton extends Button {
@Override
public boolean isInEditMode() {
    return true;
}
Paint paint=new Paint();
private static final int AnimDuration = 9000;
private TouchEffectAnimator touchEffectAnimator;

public MehDiRippleButton(Context context) {
    super(context);
    init();
}

public MehDiRippleButton(Context context, AttributeSet attrs) {
    super(context, attrs);

    allocated_TuchEffectAnimator();

    TypedArray typedArray_MehDi_rippleButton_style = context.obtainStyledAttributes(attrs,R.styleable.MehDi_rippleButton_style);
    CharSequence charSequence_buttonColor =typedArray_MehDi_rippleButton_style.getString(R.styleable.MehDi_rippleButton_style_MehDi_buttonColor);
    paint.setColor(Color.parseColor(charSequence_buttonColor.toString()));
    touchEffectAnimator.setStroke(paint);

    CharSequence charSequence_rippleColor =typedArray_MehDi_rippleButton_style.getString(R.styleable.MehDi_rippleButton_style_MehDi_rippleColor);
    if(charSequence_rippleColor!=null) {
          touchEffectAnimator.setEffectColor(Color.parseColor(charSequence_rippleColor.toString()),Color.parseColor(charSequence_buttonColor.toString()));
    }else touchEffectAnimator.setEffectColor(Color.LTGRAY,Color.WHITE);

    typedArray_MehDi_rippleButton_style.recycle();  
    init();
}

private void allocated_TuchEffectAnimator(){
    touchEffectAnimator = new TouchEffectAnimator(this); 
}

private void init() {

    touchEffectAnimator.setHasRippleEffect(true);


    touchEffectAnimator.setAnimDuration(AnimDuration);

    touchEffectAnimator.setClipRadius(0);


    setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
        }
    });
}

@Override
public boolean onTouchEvent(final MotionEvent event) {
    touchEffectAnimator.onTouchEvent(event);
    return super.onTouchEvent(event);
}

@Override
protected void onDraw(Canvas canvas) {
    touchEffectAnimator.onDraw(canvas);
    super.onDraw(canvas);
}
}

和: (在这堂课中发生了问题):

public class TouchEffectAnimator {
float u=0;
private static final int fadeout_time_helper=29;
private static final int tuchUp_time_helper=14;


private final int EASE_ANIM_DURATION = 2000;
private final int RIPPLE_ANIM_DURATION = 3000;
private final int MAX_RIPPLE_ALPHA = 255;  

private View mView;
private int mClipRadius;
private boolean hasRippleEffect = false;
private int animDuration = EASE_ANIM_DURATION;

private int requiredRadius;
private float mDownX;
private float mDownY;
private float mRadius;
private int mCircleAlpha = MAX_RIPPLE_ALPHA;
private int mRectAlpha = 0;
private Paint mCirclePaint = new Paint();
private Paint mStrokePaint = new Paint();
private Paint mRectPaint = new Paint();
private Path mCirclePath = new Path();
private Path mRectPath = new Path();
private boolean isTouchReleased = false;
private boolean isAnimatingFadeIn = false;
/**
 *
 *
 * */
private Animation.AnimationListener animationListener = new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
        isAnimatingFadeIn = true;
    }

    @Override
    public void onAnimationEnd(Animation animation) {
        isAnimatingFadeIn = false;
        if (isTouchReleased){
            setStroke(mStrokePaint);
            fadeOutEffect();
        }
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
    }
};

public TouchEffectAnimator(View mView) {
    this.mView = mView;
}

public void setHasRippleEffect(boolean hasRippleEffect) {
    this.hasRippleEffect = hasRippleEffect;
    if (hasRippleEffect) animDuration = RIPPLE_ANIM_DURATION;
}

public void setAnimDuration(int animDuration) {
    this.animDuration = animDuration;
}

public void setEffectColor(int effectColor,int buttonColor) {
    mCirclePaint.setColor(effectColor);
    mCirclePaint.setAlpha(mCircleAlpha);
    mRectPaint.setColor(effectColor);
    mRectPaint.setAlpha(mRectAlpha);
    mStrokePaint.setColor(buttonColor);
}

public void setClipRadius(int mClipRadius) {
    this.mClipRadius = mClipRadius;
}

public void onTouchEvent(final MotionEvent event) {


    if (event.getActionMasked() == MotionEvent.ACTION_UP) {
        isTouchReleased = true;

        Drawable background = mView.getBackground();
        if (background instanceof ShapeDrawable) {
            ((ShapeDrawable)background).getPaint().setStrokeWidth(0);
            Log.e("fdsfsfd","fdsfdsfdsf");
        } else if (background instanceof GradientDrawable) {
            //((GradientDrawable)background).setS
            Log.e("qqq","qqq");
        }



        ValueGeneratorAnim valueGeneratorAnim = new ValueGeneratorAnim(new InterpolatedTimeCallback() {
            @Override
            public void onTimeUpdate(float interpolatedTime) {
                if (hasRippleEffect)
                    mRadius = requiredRadius * interpolatedTime +u;
                mRectAlpha = (int) (interpolatedTime * MAX_RIPPLE_ALPHA);
                mView.invalidate();
            }
        });
        valueGeneratorAnim.setInterpolator(new DecelerateInterpolator());
        valueGeneratorAnim.setDuration(animDuration/tuchUp_time_helper);
        valueGeneratorAnim.setAnimationListener(animationListener);
        mView.startAnimation(valueGeneratorAnim);

        if (!isAnimatingFadeIn) {
            setStroke(mStrokePaint);
            fadeOutEffect();
        }

    } else if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {

        // gets the bigger value (width or height) to fit the circle
        requiredRadius = mView.getWidth() >= mView.getHeight() ? mView.getWidth() : mView.getHeight();
        final int requiredRadius2 = mView.getWidth() < mView.getHeight() ? mView.getWidth() : mView.getHeight();

        noStroke(mStrokePaint);

        requiredRadius *= 1.2;
        Log.e("req ", "" + requiredRadius);
        isTouchReleased = false;

        mDownX = event.getX();
        mDownY = mView.getMeasuredHeight()/2;

        Drawable background = mView.getBackground();
        if (background instanceof ShapeDrawable) {
            ((ShapeDrawable)background).getPaint().setStrokeWidth(0);
            Log.e("fdsfsfd","fdsfdsfdsf");
        } else if (background instanceof GradientDrawable) {
            //((GradientDrawable)background).setS
            Log.e("qqq","qqq");
        }

        mCircleAlpha = MAX_RIPPLE_ALPHA;
        mRectAlpha = 0;

        ValueGeneratorAnim valueGeneratorAnim = new ValueGeneratorAnim(new InterpolatedTimeCallback() {
            @Override
            public void onTimeUpdate(float interpolatedTime) {
                Log.e("1 ", "" + 1);
                if (hasRippleEffect)
                    mRadius = requiredRadius * interpolatedTime+(float)(requiredRadius2/1.5);
                u=mRadius;
                Log.e("mRa ", "" + mRadius);
                Log.e("int ", "" + interpolatedTime);
                mRectAlpha = (int) (interpolatedTime * MAX_RIPPLE_ALPHA);
                mView.invalidate();
            }
        });
        Log.e("222 ", "" + 222);
        valueGeneratorAnim.setInterpolator(new DecelerateInterpolator());
        valueGeneratorAnim.setDuration(animDuration);
        valueGeneratorAnim.setAnimationListener(animationListener);
        mView.startAnimation(valueGeneratorAnim);


    }
}

public void onDraw(final Canvas canvas) {

    if (hasRippleEffect) {
        mCirclePath.reset();
        mCirclePaint.setAlpha(mCircleAlpha);
        mCirclePath.addRoundRect(new RectF(0, 0, mView.getWidth(), mView.getHeight()),
                mClipRadius, mClipRadius, Path.Direction.CW);

        canvas.clipPath(mCirclePath);
        canvas.drawCircle(mDownX, mDownY, mRadius, mCirclePaint);
    }

    mRectPath.reset();

    if (hasRippleEffect && mCircleAlpha != 255) mRectAlpha = mCircleAlpha / 2;
    mRectPaint.setAlpha(mRectAlpha);
    canvas.drawRoundRect(new RectF(0, 0, mView.getWidth(), mView.getHeight()), mClipRadius,mClipRadius, mRectPaint);
}

private void fadeOutEffect() {
    ValueGeneratorAnim valueGeneratorAnim = new ValueGeneratorAnim(new InterpolatedTimeCallback() {
        @Override
        public void onTimeUpdate(float interpolatedTime) {
            mCircleAlpha = (int) (MAX_RIPPLE_ALPHA - (MAX_RIPPLE_ALPHA * interpolatedTime));
            mRectAlpha = mCircleAlpha;
            mView.invalidate();
        }
    });
    valueGeneratorAnim.setDuration(animDuration / fadeout_time_helper); /**change anim fade out time*/
    mView.startAnimation(valueGeneratorAnim);
}


class ValueGeneratorAnim extends Animation {

    private InterpolatedTimeCallback interpolatedTimeCallback;

    ValueGeneratorAnim(InterpolatedTimeCallback interpolatedTimeCallback) {
        this.interpolatedTimeCallback = interpolatedTimeCallback;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        this.interpolatedTimeCallback.onTimeUpdate(interpolatedTime);
    }
}



interface InterpolatedTimeCallback {
    public void onTimeUpdate(float interpolatedTime);
}


public void setStroke(Paint mStrokePaint){
    GradientDrawable gradiant_withStroke = new GradientDrawable();
    gradiant_withStroke.setColor(mStrokePaint.getColor());
    gradiant_withStroke.setStroke(8, Color.parseColor("#00000000"));
    mView.setBackgroundDrawable(gradiant_withStroke);
}
public void noStroke(Paint mStrokePaint){
    GradientDrawable gradiant_withStroke = new GradientDrawable();
    gradiant_withStroke.setColor(mStrokePaint.getColor());
    gradiant_withStroke.setStroke(0, Color.parseColor("#00000000"));
    mView.setBackgroundDrawable(gradiant_withStroke);
}
}

和activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical">

<com.example.mahdi.myapplication.MehDiRippleButton
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/view2"
    android:layout_gravity="center_horizontal"
    android:text="Ripple Tuch"
    app:MehDi_rippleColor="#cf030a"
    app:MehDi_buttonColor="#ff2c25"
    />
<com.example.mahdi.myapplication.MehDiRippleButton
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/view34"
    android:text="Produce By"
    app:MehDi_rippleColor="#f7f336"
    app:MehDi_buttonColor="#d3ce00"
    />

<com.example.mahdi.myapplication.MehDiRippleButton
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/view"
    android:layout_gravity="center_horizontal"
    android:text="MehDi"
    app:MehDi_rippleColor="#00930e"
    app:MehDi_buttonColor="#00b909"
/>


<com.example.mahdi.myapplication.MehDiRippleButton
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/view3"
    android:layout_gravity="center_horizontal"
    android:text="NazaRi"
    app:MehDi_rippleColor="#303dd3"
    app:MehDi_buttonColor="#7688e5"
    />

<com.example.mahdi.myapplication.MehDiRippleButton
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/view23"
    android:layout_gravity="center_horizontal"
    android:text="؛)"
    app:MehDi_rippleColor="#cf0584"
    app:MehDi_buttonColor="#ff0fb6"
    />
<com.example.mahdi.myapplication.MehDiRippleButton
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/viehw23"
    android:layout_gravity="center_horizontal"
    android:text=":D"
    app:MehDi_rippleColor="#a2a3a2"
    app:MehDi_buttonColor="#dadbda"
    />

1 个答案:

答案 0 :(得分:0)

你需要挖出执行大部分动画调用的Handler,并调用handler.removeCallbacksAndMessages(null);,这将解决一些滞后问题。

因为最有可能的是,当你完成并重新进入上述活动时,它会像第一次运行时一样快速有效。这可能是因为有很多线程或处理程序消息已经结束了它们的生命周期,但由于已经死亡而没有被删除。