मैं एंड्रॉइड में एक गेम बना रहा हूं, और मैंने देखा कि गेम में मेमोरी रिसाव है। Iv मेमोरी रिसाव को एक छोटे से एप्लिकेशन में अलग करने में कामयाब रहा ताकि मैं इसे ठीक करने का प्रयास कर सकूं और काम कर सकूं।एंड्रॉइड सर्फेसव्यू थ्रेड और मेमोरी लीक
एप्लिकेशन अपने दृश्य के लिए एक सतही दृश्य का उपयोग करता है और स्क्रीन पर सभी ड्राइंग करने के लिए उस से जुड़ा धागा है। मेमोरी रिसाव तब होता है जब मैं एक नई गतिविधि शुरू करता हूं और वर्तमान में उपयोग कर रहा हूं। मैं इसे देख सकता हूं जब मैं अपने टेस्ट एप्लिकेशन पर मेमोरी डंप करता हूं क्योंकि यह सब कुछ करता है और एक गतिविधि बंद करता है (गतिविधि ए -> गतिविधि बी -> गतिविधि ए)। Iv तरह के विचारों से बाहर निकल गया कि मैं इसे कैसे ठीक कर सकता हूं क्योंकि iv ने मेरे सभी संदर्भों को नकारने का प्रयास किया है जो मैं दृश्य (थ्रेड के अंदर) में बना हूं, iv ने दृश्य को नष्ट करने पर सतह दृश्य से कॉलबैक को हटाने का प्रयास किया, और यह भी गतिविधि के अंदर, यह कोई फर्क नहीं पड़ता है।
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;
}
}
--Edit-- मैं अपने surfaceDestroyed (SurfaceHolder धारक) को देखने के वर्ग में परिवर्तन किए इतना है कि यह दृश्य सेट हो जाएगा थ्रेड को रोकने के लिए कहा जाता है कि थ्रेड को शून्य करना है। जो परिवर्तन किए हैं
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;
}
हैं आप भी धागा वर्ग पर तो
public void surfaceCreated(SurfaceHolder holder) {
if(!this.vThread.isAlive()) {
this.vThread =new MemoryLeakViewThread();
this.vThread.setRunning(true, this);
this.vThread.start();
}
}
को surfaceCreated (SurfaceHolder धारक) विधि को बदलने की जरूरत है कि हम बदलने की जरूरत है निम्नलिखित
public MemoryLeakViewThread() {
}
public void setRunning(boolean run) {
this.run =run;
}
public void setRunning(boolean run, MemoryLeak view) {
this.run =run;
this.view =view;
}
ऐसा करने से यह समस्या को ठीक करने लग रहा था, थ्रेड क्लास और थ्रेड ग्रुप के कारण थ्रेड केवल स्मृति में रहने लगता है। लेकिन मुझे लगता है कि यह डीबगर के कारण हो सकता है।
अपवाद और स्टैक-ट्रेस जोड़ना इस मुद्दे को जानने में मदद करेगा। – Arslan
Iv थ्रेड की चलती स्थिति सेट करते समय दृश्य को पार करके अधिकांश मेमोरी लीक समस्याओं को ठीक करने में कामयाब रहा, और फिर जब मैं चल रहा स्थिति को गलत पर सेट करता हूं तो उसे शून्य पर सेट करता हूं। इसने स्मृति से दोनों गतिविधियों को हटा दिया है और अब स्मृति से एकमात्र चीज है जो धागा है जो थ्रेड ग्रुप क्लास के अंदर फंस जाता है। मुझे याद है कि वहां धागे के बारे में कुछ पढ़ना होगा अगर वहां शुरू नहीं हुआ तो मैं अभी इसे लिंक नहीं ढूंढ सकता। – Spider
http://code.google.com/p/android/issues/detail?id=7979 यह है कि। स्टैक-ट्रेस के लिए, आप मुझे अपवाद जोड़ने के लिए कहां चाहते हैं? यह किसी भी फेंक नहीं रहा है, ठीक है जब यह स्मृति से बाहर हो जाएगा, लेकिन जैसा कि मैं अपने परीक्षण आवेदन के साथ ज्यादा मेमोरी का उपयोग नहीं कर रहा हूं, इसमें कुछ समय लगेगा। मैं एक ढेर डंप का विश्लेषण करने के लिए MAT का उपयोग कर रहा हूं, इसलिए मैं देख सकता हूं कि स्मृति में क्या हो रहा है – Spider