Android Surfaceview线程和内存泄漏

概述我在 android中创建一个游戏,我注意到游戏有内存泄漏.我设法将内存泄漏隔离到一个较小的应用程序,以便我可以看到很好的尝试和解决,如何解决它. 该应用程序使用一个surfaceview作为其视图,并附加一个线程,以便完成所有绘图到屏幕.当我开始一个新活动并关闭我当前正在使用的活动时,会发生内存泄漏.当我在我的测试应用程序上执行内存转储时,我可以看到这一点,因为它只是打开并关闭一个活动(活动a 我在 android中创建一个游戏,我注意到游戏有内存泄漏.我设法将内存泄漏隔离到一个较小的应用程序,以便我可以看到很好的尝试和解决,如何解决它.

该应用程序使用一个surfacevIEw作为其视图,并附加一个线程,以便完成所有绘图到屏幕.当我开始一个新活动并关闭我当前正在使用的活动时,会发生内存泄漏.当我在我的测试应用程序上执行内存转储时,我可以看到这一点,因为它只是打开并关闭一个活动(活动a – >活动b – >活动a).我有点想法如何解决这个问题,因为iv尝试将我创建的所有引用归零(在线程内),iv尝试在我销毁视图时从surfacevIEw中删除回调,并且在活动中,它似乎没有任何区别.

MemoryLeakActivity.java

package memory.leak;import memory.leak.vIEw.MemoryLeak;import androID.app.Activity;import androID.os.Bundle;public class MemoryLeakActivity extends Activity {    /** Called when the activity is first created. */    @OverrIDe    public voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(new MemoryLeak(this));    }}

MemoryLeakVIEwThread.java

package memory.leak.thread;import memory.leak.vIEw.MemoryLeak;import androID.vIEw.SurfaceHolder;import androID.graphics.Canvas;public class MemoryLeakVIEwThread extends Thread {    private MemoryLeak vIEw;    private boolean run =false;    public MemoryLeakVIEwThread(MemoryLeak vIEw) {        this.vIEw =vIEw;    }    public voID setRunning(boolean run) {        this.run =run;    }    @OverrIDe    public voID run() {        Canvas canvas =null;        SurfaceHolder holder =this.vIEw.getHolder();        while(this.run) {            canvas =holder.lockCanvas();            if(canvas !=null) {                this.vIEw.onDraw(canvas);                holder.unlockCanvasAndPost(canvas);            }        }        holder =null;        this.vIEw =null;    }}

MemoryLeak.java

package memory.leak.vIEw;import memory.leak.TestActivity;import memory.leak.thread.MemoryLeakVIEwThread;import androID.app.Activity;import androID.content.Context;import androID.content.Intent;import androID.graphics.Canvas;import androID.graphics.color;import androID.vIEw.GestureDetector;import androID.vIEw.MotionEvent;import androID.vIEw.SurfaceHolder;import androID.vIEw.SurfaceVIEw;import androID.vIEw.GestureDetector.OnGestureListener;public class MemoryLeak extends SurfaceVIEw implements SurfaceHolder.Callback,OnGestureListener {    private GestureDetector gesture;    private MemoryLeakVIEwThread vThread;    private Context context;    public MemoryLeak(Context context) {        super(context);        this.getHolder().addCallback(this);        this.vThread =new MemoryLeakVIEwThread(this);        this.gesture =new GestureDetector(this);        this.context =context;    }    public voID surfaceChanged(SurfaceHolder holder,int format,int wIDth,int height) {}    public voID surfaceCreated(SurfaceHolder holder) {        if(!this.vThread.isAlive()) {            this.vThread =new MemoryLeakVIEwThread(this);            this.vThread.setRunning(true);            this.vThread.start();        }    }    public voID surfaceDestroyed(SurfaceHolder holder) {        boolean retry = true;        if(this.vThread.isAlive()) {            this.vThread.setRunning(false);            while(retry) {                try {                    this.vThread.join();                    retry =false;                } catch(Exception ee) {}            }        }        this.vThread =null;        this.context =null;    }     public boolean ontouchEvent(MotionEvent event) {         return this.gesture.ontouchEvent(event);     }    @OverrIDe    protected voID onSizeChanged(int w,int h,int olDW,int oldh) {    }    @OverrIDe    public voID onDraw(Canvas canvas) {        canvas.drawcolor(color.WHITE);    }       @OverrIDe    public boolean onDown(MotionEvent e) {        return true;    }    @OverrIDe    public boolean onFling(MotionEvent e1,MotionEvent e2,float veLocityX,float veLocityY) {        return false;    }    @OverrIDe    public voID onLongPress(MotionEvent e) {}    @OverrIDe    public boolean onScroll(MotionEvent e1,float distanceX,float distanceY) {        return false;    }    @OverrIDe    public voID onShowPress(MotionEvent e) {}    @OverrIDe    public boolean onSingleTapUp(MotionEvent e) {        Intent helpScreenIntent =new Intent(this.context,TestActivity.class);        this.context.startActivity(helpScreenIntent);        if (this.context instanceof Activity)            ((Activity) this.context).finish();        return true;    }}

TestActivity.java

package memory.leak;import memory.leak.vIEw.Test;import androID.app.Activity;import androID.os.Bundle;public class TestActivity extends Activity {    /** Called when the activity is first created. */    @OverrIDe    public voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(new Test(this));    }}

TestVIEwThread.java

package memory.leak.thread;import memory.leak.vIEw.Test;import androID.vIEw.SurfaceHolder;import androID.graphics.Canvas;public class TestVIEwThread extends Thread {    private Test panel;    private boolean run =false;    public TestVIEwThread(Test panel) {        this.panel =panel;    }    public voID setRunning(boolean run) {        this.run =run;    }    @OverrIDe    public voID run() {        Canvas canvas =null;        SurfaceHolder holder =this.panel.getHolder();        while(this.run) {            canvas =holder.lockCanvas();            if(canvas !=null) {                this.panel.onDraw(canvas);                holder.unlockCanvasAndPost(canvas);            }        }        holder =null;        this.panel =null;    }}

Test.java

package memory.leak.vIEw;import memory.leak.MemoryLeakActivity;import memory.leak.thread.TestVIEwThread;import androID.app.Activity;import androID.content.Context;import androID.content.Intent;import androID.graphics.Canvas;import androID.graphics.color;import androID.vIEw.GestureDetector;import androID.vIEw.MotionEvent;import androID.vIEw.SurfaceHolder;import androID.vIEw.SurfaceVIEw;import androID.vIEw.GestureDetector.OnGestureListener;public class Test extends SurfaceVIEw implements SurfaceHolder.Callback,OnGestureListener {    private GestureDetector gesture;    private TestVIEwThread vThread;    private Context context;    public Test(Context context) {        super(context);        this.getHolder().addCallback(this);        this.vThread =new TestVIEwThread(this);        this.gesture =new GestureDetector(this);        this.context =context;    }    public voID surfaceChanged(SurfaceHolder holder,int height) {}    public voID surfaceCreated(SurfaceHolder holder) {        if(!this.vThread.isAlive()) {            this.vThread =new TestVIEwThread(this);            this.vThread.setRunning(true);            this.vThread.start();        }    }    public voID surfaceDestroyed(SurfaceHolder holder) {        boolean retry = true;        if(this.vThread.isAlive()) {            this.vThread.setRunning(false);            while(retry) {                try {                    this.vThread.join();                    retry =false;                } catch(Exception ee) {}            }        }        this.vThread =null;        this.context =null;    }     public boolean ontouchEvent(MotionEvent event) {         return this.gesture.ontouchEvent(event);     }    @OverrIDe    protected voID onSizeChanged(int w,int oldh) {    }    @OverrIDe    public voID onDraw(Canvas canvas) {        canvas.drawcolor(color.RED);    }       @OverrIDe    public boolean onDown(MotionEvent e) {        return true;    }    @OverrIDe    public boolean onFling(MotionEvent e1,MemoryLeakActivity.class);        this.context.startActivity(helpScreenIntent);        if (this.context instanceof Activity)            ((Activity) this.context).finish();        return true;    }}

– 编辑 –
我将视图类更改为其surfaceDestroyed(SurfaceHolder持有者),以便在线程被告知停止时,它将设置线程必须为null的视图.我所做的改变是

public voID surfaceDestroyed(SurfaceHolder holder) {        boolean retry = true;        if(this.vThread.isAlive()) {            this.vThread.setRunning(false);            while(retry) {                try {                    this.vThread.join();                    retry =false;                } catch(Exception ee) {}            }            this.vThread.setRunning(false,null);        }        this.vThread =null;        this.context =null;        this.gesture =null;    }

您还需要将surfaceCreated(SurfaceHolder holder)方法更改为

public voID surfaceCreated(SurfaceHolder holder) {        if(!this.vThread.isAlive()) {            this.vThread =new MemoryLeakVIEwThread();            this.vThread.setRunning(true,this);            this.vThread.start();        }    }

然后在线程类我们需要更改以下内容

public MemoryLeakVIEwThread() {    }    public voID setRunning(boolean run) {        this.run =run;    }    public voID setRunning(boolean run,MemoryLeak vIEw) {        this.run =run;        this.vIEw =vIEw;    }

通过这样做似乎解决了问题,现在唯一的问题是线程似乎留在内存中,由于线程类和线程组.但我认为这可能是由于调试器.

解决方法 在onSurfaceCreated中创建新的Thread时,不应该在构造函数中创建新的Thread.将您的代码与我的示例进行比较: How can I use the animation framework inside the canvas? 总结

以上是内存溢出为你收集整理的Android Surfaceview线程和内存泄漏全部内容,希望文章能够帮你解决Android Surfaceview线程和内存泄漏所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1138267.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-30
下一篇 2022-05-30

发表评论

登录后才能评论

评论列表(0条)

保存