该应用程序使用一个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线程和内存泄漏所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)