Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/220.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android内存泄漏自定义视图_Android_Memory Leaks_Android Custom View - Fatal编程技术网

Android内存泄漏自定义视图

Android内存泄漏自定义视图,android,memory-leaks,android-custom-view,Android,Memory Leaks,Android Custom View,我正在尝试制作一个小应用程序。此应用程序具有活动、自定义视图类和服务 1) 新数据和重画自定义视图的活动请求服务 2) 服务正在登录蓝牙设备并解析数据 一切都很好,但我注意到应用程序在运行40分钟后速度变慢了 我做了另一个项目删除服务,发现它也变慢了!所以问题是我的Customview类,也许我在服务中有内存泄漏。。。但我100%都有绘画方面的问题 我发现我在onDraw()方法上创建了一些对象。。我试图将所有这些员工转移到onSizeChanged()-但会有更多的延迟 现在我需要帮助。我需要

我正在尝试制作一个小应用程序。此应用程序具有活动、自定义视图类和服务

1) 新数据和重画自定义视图的活动请求服务 2) 服务正在登录蓝牙设备并解析数据

一切都很好,但我注意到应用程序在运行40分钟后速度变慢了

我做了另一个项目删除服务,发现它也变慢了!所以问题是我的Customview类,也许我在服务中有内存泄漏。。。但我100%都有绘画方面的问题

我发现我在onDraw()方法上创建了一些对象。。我试图将所有这些员工转移到onSizeChanged()-但会有更多的延迟

现在我需要帮助。我需要一些依赖于设备宽度和高度的简单绘图示例(我认为我的方法是错误的——我使用我的“设计”的比例来计算px中的尺寸)

顺便说一句,我使用的是animator,它可以使动画更加平滑。)

公共类动态{
/**
*用于比较浮动,如果差值小于此值,则为
*平等的
*/
专用静态最终浮动公差=0.01f;
/**动力学应该处于的位置*/
私人浮动目标定位;
/**动力学的当前位置*/
私人浮动头寸;
/**动力学的流速*/
私人浮动速度;
/**上次更新发生的时间*/
私人长时间;
/**动力学所具有的弹性量*/
私人浮动弹性;
/**动力学所具有的阻尼*/
私人双阻尼;
公共动力(浮动弹性、浮动阻尼){
这个。弹性=弹性;
this.damping=dampingRatio*2*Math.sqrt(弹性);
}
公共无效设置位置(浮动位置,多头){
这个位置=位置;
上次=现在;
}
公共空间设置速度(浮动速度,长时间){
速度=速度;
上次=现在;
}
public void setTargetPosition(浮动targetPosition,多头){
this.targetPosition=targetPosition;
上次=现在;
}
公共无效更新(现在很长){
float dt=数学最小值(现在-上次,50)/1000f;
浮动x=位置-目标位置;
双加速度=-弹性*x-阻尼*速度;
速度+=加速度*dt;
位置+=速度*dt;
上次=现在;
}
公共布尔值isAtRest(){
最终布尔标准=数学abs(速度)<公差;
最终布尔值IsAttTarget=(targetPosition-position)<公差;
返回standingStill&isAtTarget;
}
公众职位(){
返回位置;
}
公共浮点数getTargetPos(){
返回目标位置;
}
公共浮点getVelocity(){
返回速度;
}
}
在我的自定义视图中,我有以下设置来设置新数据:

public void  SetData(int[] NewData2,float[]newDatapoints)
{


    this.NewData=NewData2;

    long now = AnimationUtils.currentAnimationTimeMillis();
    if (datapoints == null || datapoints.length != newDatapoints.length) {
        datapoints = new Dynamics[newDatapoints.length];
        for (int i = 0; i < newDatapoints.length; i++) {
            datapoints[i] = new Dynamics(70f, 0.50f);
            datapoints[i].setPosition(newDatapoints[i], now);
            datapoints[i].setTargetPosition(newDatapoints[i], now);
        }
        invalidate();
    } else {
        for (int i = 0; i < newDatapoints.length; i++) {
            datapoints[i].setTargetPosition(newDatapoints[i], now);
        }
        removeCallbacks(animator);
        post(animator);
    }
    LastData=NewData;

    //redraw();
}
public void SetData(int[]NewData2,float[]newDatapoints)
{
this.NewData=NewData2;
long now=AnimationUtils.currentAnimationTimeMillis();
if(datapoints==null | | datapoints.length!=newDatapoints.length){
datapoints=新动力学[newDatapoints.length];
对于(int i=0;i
这是我的自定义视图的“代码”,经过所有的更改后,它看起来是可编辑的,所以我将其削减了90%。我制作了一些测试代码:

        import android.content.Context;
        import android.content.res.AssetManager;
        import android.content.res.TypedArray;
        import android.graphics.Canvas;
        import android.graphics.Color;
        import android.graphics.ComposeShader;
        import android.graphics.LinearGradient;
        import android.graphics.Paint;
        import android.graphics.Paint.Style;
        import android.graphics.Path;
        import android.graphics.PorterDuff;
        import android.graphics.RadialGradient;
        import android.graphics.RectF;
        import android.graphics.Shader;
        import android.graphics.Typeface;
        import android.graphics.drawable.Drawable;
        import android.util.AttributeSet;
        import android.util.DisplayMetrics;
        import android.view.View;
        import android.view.animation.AnimationUtils;

        import java.io.IOException;
        import java.math.RoundingMode;
        import java.text.DecimalFormat;
        import java.util.Random;



public class CustomDisplayView extends View {



    //paint for drawing custom view
    private Paint RectPaint = new Paint();

    //Динамические данные float
    private Dynamics[] datapoints;
    //Динамические статические Int
    private int[] NewData = new int[500];
    //созадем новый объект квадрат
    private RectF rectf= new RectF();

    //Задаем массив динамических цветов
    int[] CurColors= new int[100];
    int[] TargetColors= new int[100];

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

        //Установка парметров красок
        RectPaint.setAntiAlias(true);



    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (w != 0 && h != 0) {
            //create Bitmap here

        }

    }

    /**
     * Override the onDraw method to specify custom view appearance using canvas
     */
       @Override
    protected void onDraw(Canvas canvas) {

        //Get Screen size
        //int viewWidth=this.getMeasuredWidth();
       // int viewHeight = this.getMeasuredHeight();


        //Выводим код цвета

        RectPaint.setColor(0xff000000);
        RectPaint.setTextSize(40);


        canvas.restore();
        canvas.drawText("V: " + datapoints[1].getPosition(), 20, 60, RectPaint);

        //int saveCount = canvas.save();
        for(int a=0;a<1000;a++)
        {
            rectf.set(datapoints[a].getPosition(), datapoints[a + 1].getPosition(), datapoints[a].getPosition() + datapoints[a + 1].getPosition() / 10, datapoints[a + 1].getPosition() + datapoints[a + 1].getPosition() / 10);

            RectPaint.setColor(0x88005020);
            //RectPaint.setColor(CurColor[a]);
            //canvas.rotate(datapoints[1].getPosition(), viewWidth/2, viewHeight/2);
            canvas.drawRoundRect(rectf, 0, 0, RectPaint);
            //canvas.restore();
        }
        //canvas.restoreToCount(saveCount);


/*
        for(int a=0;a<999;a++)
        {
            CurColors[a]=progressiveColor(CurColors[a], TargetColors[a], 2);
            if(CurColors[a]==TargetColors[a])
            {
                TargetColors[a]=randomColor();
            }
        }
*/

        canvas.restore();
    }



    //Рандом колор
    public static int randomColor(){
        Random random = new Random();
        int[] ColorParams= new int[4];
        ColorParams[0]=random.nextInt(235)+20;
        ColorParams[1]=random.nextInt(255);
        ColorParams[2]=random.nextInt(255);
        ColorParams[3]=random.nextInt(255);
        return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);

    }

    //Интерполяция цвета
    public static int progressiveColor(int CurColor,int TargetColor,int Step){

        //Current color
        int[] ColorParams= new int[4];
        ColorParams[0]=(CurColor >> 24) & 0xFF;
        ColorParams[1]=(CurColor >> 16) & 0xFF;
        ColorParams[2]=(CurColor >> 8) & 0xFF;
        ColorParams[3]=CurColor & 0xFF;



        //TargetColor
        int[] TargetColorParams= new int[4];
        TargetColorParams[0]=(TargetColor >> 24) & 0xFF;
        TargetColorParams[1]=(TargetColor >> 16) & 0xFF;
        TargetColorParams[2]=(TargetColor >> 8) & 0xFF;
        TargetColorParams[3]=TargetColor & 0xFF;

        for(int i=0;i<4;i++)
        {
            if(ColorParams[i]<TargetColorParams[i])
            {
                ColorParams[i]+=Step;
                if(ColorParams[i]>TargetColorParams[i])
                {
                    ColorParams[i]=TargetColorParams[i];
                }
            }
            else if(ColorParams[i]>TargetColorParams[i])
            {
                ColorParams[i]-=Step;
                if(ColorParams[i]<TargetColorParams[i])
                {
                    ColorParams[i]=TargetColorParams[i];
                }
            }
        }

        //int red = r - (int)((float)(r*255)/(float)all);
        //int green = (int)((float)(g*255)/(float)all);
        return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);
        //return String.format("#%06X", (0xFFFFFF & Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3])));
        //return " "+opacity+" "+red+" "+green+" "+blue;
    }








    //each custom attribute should have a get and set method
    //this allows updating these properties in Java
    //we call these in the main Activity class



    /**
     * Get the current text label color
     * @return color as an int
     */
    public int getLabelColor(){
        return 1;
    }

    /**
     * Set the label color
     * @param newColor new color as an int
     */
    public void setLabelColor(int newColor){
        //update the instance variable
        //labelCol=newColor;
        //redraw the view
        invalidate();
        requestLayout();
    }



    public void redraw(){
        //redraw the view
        invalidate();
        requestLayout();
    }



    public void  SetData(int[] NewData2,float[]newDatapoints)
    {


        this.NewData=NewData2;

        long now = AnimationUtils.currentAnimationTimeMillis();
        if (datapoints == null || datapoints.length != newDatapoints.length) {
            datapoints = new Dynamics[newDatapoints.length];
            for (int i = 0; i < newDatapoints.length; i++) {
                datapoints[i] = new Dynamics(70f, 0.50f);
                datapoints[i].setPosition(newDatapoints[i], now);
                datapoints[i].setTargetPosition(newDatapoints[i], now);
            }
            invalidate();
        } else {
            for (int i = 0; i < newDatapoints.length; i++) {
                datapoints[i].setTargetPosition(newDatapoints[i], now);
            }
            removeCallbacks(animator);
            post(animator);
        }


        //redraw();
    }

    public int GetAction(float x,float y)
    {
        /*
        if(x>(DicsCenterX-LineHalfSpeedZone) && x<(DicsCenterX+LineHalfSpeedZone) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
        {
            // private int SpeedZoneRadius2=0;
            // private int PowerOutRadius=0;
            //Смена режима
            //начинаем смену размеру index / ms
            ChangeVal(0,700);

            return 1;
        }
        else if(x>(CofCantBGDrop*2) && x<(CofCantBGDrop*4) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
        {
            return 2;
        }
        else
        {
            return 0;
        }
        //return 0;

        */
        return 1;
    }


    public static String fmt(double d)
    {
        double val =  d/100;
        String result;
        if(val == (long) val)
            result= String.format("%d",(long)d);
        else
            result= String.format("%s",d);

        if(result.length()<2)
        {
            String result2=result;
            result="0"+result2;
        }

        return result;
    }


    private Runnable animator = new Runnable() {
        @Override
        public void run() {
            boolean needNewFrame = false;
            long now = AnimationUtils.currentAnimationTimeMillis();
            for (Dynamics dynamics : datapoints) {
                dynamics.update(now);
                if (!dynamics.isAtRest()) {
                    needNewFrame = true;
                }
            }
            if (needNewFrame) {
                postDelayed(this, 15);
            }
            invalidate();
        }
    };

}
导入android.content.Context;
导入android.content.res.AssetManager;
导入android.content.res.TypedArray;
导入android.graphics.Canvas;
导入android.graphics.Color;
导入android.graphics.ComposeShader;
导入android.graphics.LinearGradient;
导入android.graphics.Paint;
导入android.graphics.Paint.Style;
导入android.graphics.Path;
导入android.graphics.PorterDuff;
导入android.graphics.RadialGradient;
导入android.graphics.RectF;
导入android.graphics.Shader;
导入android.graphics.Typeface;
导入android.graphics.drawable.drawable;
导入android.util.AttributeSet;
导入android.util.DisplayMetrics;
导入android.view.view;
导入android.view.animation.AnimationUtils;
导入java.io.IOException;
导入java.math.RoundingMode;
导入java.text.DecimalFormat;
导入java.util.Random;
公共类CustomDisplayView扩展了视图{
//绘制自定义视图的绘制
私有油漆RectPaint=新油漆();
//浮子
私有动态[]数据点;
//内部
私有整数[]新数据=新整数[500];
//созадем новый объект квадрат
private RectF RectF=new RectF();
//Задаем массив динамических цветов
int[]CurColors=新int[100];
int[]TargetColors=新int[100];
公共CustomDisplayView(上下文、属性集属性){
超级(上下文,attrs);
//Установка парметров красок
RectPaint.setAntiAlias(true);
}
@凌驾
已更改尺寸的受保护空心(整数w、整数h、整数oldw、整数oldh){
如果(w!=0&&h!=0){
//在此处创建位图
}
}
/**
*重写onDraw方法以使用画布指定自定义视图外观
*/
@凌驾
        import android.content.Context;
        import android.content.res.AssetManager;
        import android.content.res.TypedArray;
        import android.graphics.Canvas;
        import android.graphics.Color;
        import android.graphics.ComposeShader;
        import android.graphics.LinearGradient;
        import android.graphics.Paint;
        import android.graphics.Paint.Style;
        import android.graphics.Path;
        import android.graphics.PorterDuff;
        import android.graphics.RadialGradient;
        import android.graphics.RectF;
        import android.graphics.Shader;
        import android.graphics.Typeface;
        import android.graphics.drawable.Drawable;
        import android.util.AttributeSet;
        import android.util.DisplayMetrics;
        import android.view.View;
        import android.view.animation.AnimationUtils;

        import java.io.IOException;
        import java.math.RoundingMode;
        import java.text.DecimalFormat;
        import java.util.Random;



public class CustomDisplayView extends View {



    //paint for drawing custom view
    private Paint RectPaint = new Paint();

    //Динамические данные float
    private Dynamics[] datapoints;
    //Динамические статические Int
    private int[] NewData = new int[500];
    //созадем новый объект квадрат
    private RectF rectf= new RectF();

    //Задаем массив динамических цветов
    int[] CurColors= new int[100];
    int[] TargetColors= new int[100];

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

        //Установка парметров красок
        RectPaint.setAntiAlias(true);



    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (w != 0 && h != 0) {
            //create Bitmap here

        }

    }

    /**
     * Override the onDraw method to specify custom view appearance using canvas
     */
       @Override
    protected void onDraw(Canvas canvas) {

        //Get Screen size
        //int viewWidth=this.getMeasuredWidth();
       // int viewHeight = this.getMeasuredHeight();


        //Выводим код цвета

        RectPaint.setColor(0xff000000);
        RectPaint.setTextSize(40);


        canvas.restore();
        canvas.drawText("V: " + datapoints[1].getPosition(), 20, 60, RectPaint);

        //int saveCount = canvas.save();
        for(int a=0;a<1000;a++)
        {
            rectf.set(datapoints[a].getPosition(), datapoints[a + 1].getPosition(), datapoints[a].getPosition() + datapoints[a + 1].getPosition() / 10, datapoints[a + 1].getPosition() + datapoints[a + 1].getPosition() / 10);

            RectPaint.setColor(0x88005020);
            //RectPaint.setColor(CurColor[a]);
            //canvas.rotate(datapoints[1].getPosition(), viewWidth/2, viewHeight/2);
            canvas.drawRoundRect(rectf, 0, 0, RectPaint);
            //canvas.restore();
        }
        //canvas.restoreToCount(saveCount);


/*
        for(int a=0;a<999;a++)
        {
            CurColors[a]=progressiveColor(CurColors[a], TargetColors[a], 2);
            if(CurColors[a]==TargetColors[a])
            {
                TargetColors[a]=randomColor();
            }
        }
*/

        canvas.restore();
    }



    //Рандом колор
    public static int randomColor(){
        Random random = new Random();
        int[] ColorParams= new int[4];
        ColorParams[0]=random.nextInt(235)+20;
        ColorParams[1]=random.nextInt(255);
        ColorParams[2]=random.nextInt(255);
        ColorParams[3]=random.nextInt(255);
        return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);

    }

    //Интерполяция цвета
    public static int progressiveColor(int CurColor,int TargetColor,int Step){

        //Current color
        int[] ColorParams= new int[4];
        ColorParams[0]=(CurColor >> 24) & 0xFF;
        ColorParams[1]=(CurColor >> 16) & 0xFF;
        ColorParams[2]=(CurColor >> 8) & 0xFF;
        ColorParams[3]=CurColor & 0xFF;



        //TargetColor
        int[] TargetColorParams= new int[4];
        TargetColorParams[0]=(TargetColor >> 24) & 0xFF;
        TargetColorParams[1]=(TargetColor >> 16) & 0xFF;
        TargetColorParams[2]=(TargetColor >> 8) & 0xFF;
        TargetColorParams[3]=TargetColor & 0xFF;

        for(int i=0;i<4;i++)
        {
            if(ColorParams[i]<TargetColorParams[i])
            {
                ColorParams[i]+=Step;
                if(ColorParams[i]>TargetColorParams[i])
                {
                    ColorParams[i]=TargetColorParams[i];
                }
            }
            else if(ColorParams[i]>TargetColorParams[i])
            {
                ColorParams[i]-=Step;
                if(ColorParams[i]<TargetColorParams[i])
                {
                    ColorParams[i]=TargetColorParams[i];
                }
            }
        }

        //int red = r - (int)((float)(r*255)/(float)all);
        //int green = (int)((float)(g*255)/(float)all);
        return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);
        //return String.format("#%06X", (0xFFFFFF & Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3])));
        //return " "+opacity+" "+red+" "+green+" "+blue;
    }








    //each custom attribute should have a get and set method
    //this allows updating these properties in Java
    //we call these in the main Activity class



    /**
     * Get the current text label color
     * @return color as an int
     */
    public int getLabelColor(){
        return 1;
    }

    /**
     * Set the label color
     * @param newColor new color as an int
     */
    public void setLabelColor(int newColor){
        //update the instance variable
        //labelCol=newColor;
        //redraw the view
        invalidate();
        requestLayout();
    }



    public void redraw(){
        //redraw the view
        invalidate();
        requestLayout();
    }



    public void  SetData(int[] NewData2,float[]newDatapoints)
    {


        this.NewData=NewData2;

        long now = AnimationUtils.currentAnimationTimeMillis();
        if (datapoints == null || datapoints.length != newDatapoints.length) {
            datapoints = new Dynamics[newDatapoints.length];
            for (int i = 0; i < newDatapoints.length; i++) {
                datapoints[i] = new Dynamics(70f, 0.50f);
                datapoints[i].setPosition(newDatapoints[i], now);
                datapoints[i].setTargetPosition(newDatapoints[i], now);
            }
            invalidate();
        } else {
            for (int i = 0; i < newDatapoints.length; i++) {
                datapoints[i].setTargetPosition(newDatapoints[i], now);
            }
            removeCallbacks(animator);
            post(animator);
        }


        //redraw();
    }

    public int GetAction(float x,float y)
    {
        /*
        if(x>(DicsCenterX-LineHalfSpeedZone) && x<(DicsCenterX+LineHalfSpeedZone) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
        {
            // private int SpeedZoneRadius2=0;
            // private int PowerOutRadius=0;
            //Смена режима
            //начинаем смену размеру index / ms
            ChangeVal(0,700);

            return 1;
        }
        else if(x>(CofCantBGDrop*2) && x<(CofCantBGDrop*4) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
        {
            return 2;
        }
        else
        {
            return 0;
        }
        //return 0;

        */
        return 1;
    }


    public static String fmt(double d)
    {
        double val =  d/100;
        String result;
        if(val == (long) val)
            result= String.format("%d",(long)d);
        else
            result= String.format("%s",d);

        if(result.length()<2)
        {
            String result2=result;
            result="0"+result2;
        }

        return result;
    }


    private Runnable animator = new Runnable() {
        @Override
        public void run() {
            boolean needNewFrame = false;
            long now = AnimationUtils.currentAnimationTimeMillis();
            for (Dynamics dynamics : datapoints) {
                dynamics.update(now);
                if (!dynamics.isAtRest()) {
                    needNewFrame = true;
                }
            }
            if (needNewFrame) {
                postDelayed(this, 15);
            }
            invalidate();
        }
    };

}
if (needNewFrame) {
    postDelayed(this, 15);  <--- memory leak
} 
@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    removeCallback(your runnable);
}