概述
我在
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, MotionEvent e2, 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 format, int width, 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 h, int oldw, 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, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {}
@Override
public boolean onSingleTapUp(MotionEvent e) {
Intent helpScreenIntent =new Intent(this.context, 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;
}
通过这样做似乎解决了问题,现在唯一的问题是线程似乎留在内存中,由于线程类和线程组.但我认为这可能是由于调试器.
最后
以上就是强健彩虹为你收集整理的android surfaceview 多线程,Android Surfaceview线程和内存泄漏的全部内容,希望文章能够帮你解决android surfaceview 多线程,Android Surfaceview线程和内存泄漏所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复