我的应用在首次运行时运行良好。然后,当我终止并再次运行它时,它只会调出强制关闭窗口。强制关闭应用程序后,它再次正常运行。该应用程序在强制关闭和运行正常之间交替。
我在应用程序终止之前错过了一些清理工作吗?
以下是我的一些代码(包含三个类,foobar,actionview& actionthread:
foobar.java:
public class foobar extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new ActionView(this));
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStop() {
super.onStop();
}
}
public class ActionView extends SurfaceView implements SurfaceHolder.Callback {
private ActionThread actionThread;
public ActionView(Context context)
{
super(context);
getHolder().addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
actionThread = new ActionThread(holder,this);
actionThread.setRunning(true);
actionThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
while(retry)
{
try
{
actionThread.join();
retry=false;
}
catch(InterruptedException e)
{
}
}
}
protected void displayGameState(Canvas canvas)
{
//code...
}
public void updateGameState()
{
//code..
if something happens then
actionThread.setRunning(false);
((Activity)getContext()).finish();
}
}
ActionThread.java:
public class ActionThread extends Thread {
private boolean threadIsRunning;
private SurfaceHolder surfaceHolder;
private ActionView actionView;
private final static int MAX_FPS = 50;
private final static int MAX_FRAME_SKIPS = 5;
private final static int FRAME_PERIOD = 1000/MAX_FPS;
private static final String TAG = ActionThread.class.getSimpleName();
public ActionThread(SurfaceHolder holder, ActionView actionView) {
this.actionView= actionView;
surfaceHolder = holder;
}
public void setRunning(boolean running)
{
threadIsRunning = running;
}
@Override
public void run()
{
long tickCount = 0L;
long totalFramesSkipped = 0L;
Canvas canvas = null;
long beginTime; //time the cycle began
long timeDiff; //time it took for cycle to execute
int sleepTime; //milliseconds to sleep (< 0 if time it took to complete cycle is longer than FRAME_PERIOD
int framesSkipped; //# of frames being skipped
while(threadIsRunning)
{
tickCount++;
try
{
canvas = surfaceHolder.lockCanvas();
synchronized(surfaceHolder)
{
beginTime = System.currentTimeMillis();
framesSkipped = 0;
actionView.updateGameState();
actionView.displayGameState(canvas);
//calc how long the cycle took
timeDiff = System.currentTimeMillis() - beginTime;
//calc sleep time
sleepTime = (int)(FRAME_PERIOD - timeDiff);
if(sleepTime > 0)
{
//if sleepTime > 0 , didn't fall behind. Try to sleep
try
{
Thread.sleep(sleepTime);
}
catch(InterruptedException e){}
}
while(sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS)
{ //fell behind and need to catch up (update without displaying)
actionView.updateGameState();
sleepTime+=FRAME_PERIOD; //add frame period to check if in next frame
framesSkipped++;
totalFramesSkipped++;
}
}
}
finally
{
if(canvas != null)
{
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
这是logcat错误:
05-03 22:47:45.449: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 36955K/38794K, paused 32ms
05-03 22:47:45.488: I/dalvikvm-heap(30596): Clamp target GC heap from 43.427MB to 42.000MB
05-03 22:47:45.488: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37165K/38794K, paused 18ms
05-03 22:47:45.535: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37165K/38794K, paused 29ms
05-03 22:47:45.574: I/dalvikvm-heap(30596): Clamp target GC heap from 43.674MB to 42.000MB
05-03 22:47:45.582: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37418K/38794K, paused 18ms
05-03 22:47:45.613: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37244K/38794K, paused 30ms
05-03 22:47:45.652: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.652: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.684: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37551K/38794K, paused 27ms
05-03 22:47:45.699: E/dalvikvm-heap(30596): 258908-byte external allocation too large for this process.
05-03 22:47:45.723: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.723: D/dalvikvm(30596): GC_FOR_MALLOC freed <1K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.723: D/GraphicsJNI(30596): Waiting for heap walker to free more memory
05-03 22:47:45.723: D/GraphicsJNI(30596): Heap walker done, retry to allocate
05-03 22:47:45.754: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37298K/38794K, paused 27ms
05-03 22:47:45.793: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.793: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.832: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37551K/38794K, paused 26ms
05-03 22:47:45.840: E/dalvikvm-heap(30596): 313968-byte external allocation too large for this process.
05-03 22:47:45.871: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.871: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.871: D/GraphicsJNI(30596): Waiting for heap walker to free more memory
05-03 22:47:45.871: D/GraphicsJNI(30596): Heap walker done, retry to allocate
05-03 22:47:45.902: D/dalvikvm(30596): GC_EXTERNAL_ALLOC freed <1K, 43% free 3126K/5447K, external 37551K/38794K, paused 30ms
05-03 22:47:45.910: E/dalvikvm-heap(30596): 313968-byte external allocation too large for this process.
05-03 22:47:45.941: I/dalvikvm-heap(30596): Clamp target GC heap from 43.804MB to 42.000MB
05-03 22:47:45.941: D/dalvikvm(30596): GC_FOR_MALLOC freed 0K, 43% free 3126K/5447K, external 37551K/38794K, paused 17ms
05-03 22:47:45.941: E/GraphicsJNI(30596): VM won't let us allocate 313968 bytes
05-03 22:47:45.957: D/AndroidRuntime(30596): Shutting down VM
05-03 22:47:45.957: W/dalvikvm(30596): threadid=1: thread exiting with uncaught exception (group=0x4001e560)
05-03 22:47:45.965: E/AndroidRuntime(30596): FATAL EXCEPTION: main
05-03 22:47:45.965: E/AndroidRuntime(30596): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.graphics.Bitmap.nativeCreate(Native Method)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.graphics.Bitmap.createBitmap(Bitmap.java:507)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.graphics.Bitmap.createBitmap(Bitmap.java:474)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:379)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.somecomany.foobar.Element.Element.resizeBitmap(Element.java:48)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.somecomany.foobar.Element.Element.<init>(Element.java:31)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.somecomany.foobar.Element.MobileElement.<init>(MobileElement.java:24)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.somecomany.foobar.ActionView.surfaceCreated(ActionView.java:156)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.SurfaceView.updateWindow(SurfaceView.java:543)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.SurfaceView.dispatchDraw(SurfaceView.java:348)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.View.draw(View.java:6883)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.widget.FrameLayout.draw(FrameLayout.java:357)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.View.draw(View.java:6883)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.widget.FrameLayout.draw(FrameLayout.java:357)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2106)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewRoot.draw(ViewRoot.java:1562)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewRoot.performTraversals(ViewRoot.java:1298)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.view.ViewRoot.handleMessage(ViewRoot.java:1911)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.os.Handler.dispatchMessage(Handler.java:99)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.os.Looper.loop(Looper.java:130)
05-03 22:47:45.965: E/AndroidRuntime(30596): at android.app.ActivityThread.main(ActivityThread.java:3821)
05-03 22:47:45.965: E/AndroidRuntime(30596): at java.lang.reflect.Method.invokeNative(Native Method)
05-03 22:47:45.965: E/AndroidRuntime(30596): at java.lang.reflect.Method.invoke(Method.java:507)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
05-03 22:47:45.965: E/AndroidRuntime(30596): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
05-03 22:47:45.965: E/AndroidRuntime(30596): at dalvik.system.NativeStart.main(Native Method)
05-03 22:47:49.996: I/Process(30596): Sending signal. PID: 30596 SIG: 9
答案 0 :(得分:1)
从日志中看,您在创建位图时会出现内存泄漏,当您有一些大型对象闲置时,可能会在第二次运行应用程序时通过静态数据结构。
另一个变体场景是在静态变量中引用Context或Activity,这基本上会阻止先前的Activity被垃圾回收。
这是因为当您在Android中“退出”某个应用时,其进程不一定会终止。因此,当您再次运行它时,操作系统可以跳过一些耗时的步骤,并且可以更快地启动应用程序。当你保留一些数据以便快速重用时,这是很好的,当你无意中保留一些(巨大的)数据然后再次尝试重新创建这些数据时,这是非常糟糕的,那就是事情发展的时候。
答案 1 :(得分:0)
尝试将Activity的LaunchMode设置为SingleTop。
你应该在Activity onDestroy时释放资源。祝你好运。