2012-05-04 6 views
1

내 앱이 처음 실행될 때 정상적으로 실행됩니다. 그런 다음 종료하고 다시 실행하면 강제 종료 창을 표시합니다. 앱을 강제 종료 한 후에 다시 정상적으로 실행됩니다. 앱을 닫으면 강제 종료되고 정상적으로 실행됩니다.두 번째 실행시 Android 앱 강제 종료

내가 앱이 종료되기 전에 정리가 누락 되었습니까?

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); 
       } 
      } 
     } 
    } 

} 

가있다

다음은 내 코드의 일부는 (세 개의 클래스는 foobar, actionview & actionthread을 포함합니다 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 
+1

logcat 오류를 표시하십시오. –

+0

내 추측은 표면 뷰 루프를 멈추지 않고 캔버스를 잠금 해제하지 않기 때문입니다. 당신의 활동의 온 디스트로에 서페이스 뷰를 멈추게하십시오. – L7ColWinters

+0

무엇이 잘못되었는지를 결정하기 위해 logcat 출력이 필요합니다. –

답변

1

로그에서 비트 맵을 생성하는 동안 메모리 누수가있는 것처럼 보입니다. 비트 맵을 생성하는 동안 응용 프로그램을 다시 실행할 때 정적 데이터 구조를 통해 크기가 큰 일부 객체가있을 때 발생합니다.

또 다른 변형 시나리오는 컨텍스트 또는 활동을 정적 변수에서 참조 할 때입니다. 기본적으로 이전 활동이 가비지 수집되지 않습니다.

Android에서 앱을 '종료'할 때 프로세스가 종료되지 않을 수 있기 때문에 이러한 현상이 발생합니다. 따라서 OS를 다시 실행할 때 OS가 시간을 많이 소비하는 단계를 건너 뛸 수 있으므로 앱을 더 빨리 시작할 수 있습니다. 이는 데이터를 빠르게 재사용 할 수 있도록 유지할 때 유용합니다. 실수로 (대용량) 데이터를 실수로 지우고 다시 데이터를 다시 만들려고 할 때 상황이 호황을 맞을 때 매우 나쁩니다.

+0

) 정적인지 여부에 관계없이 모든 객체의 파괴를 어떻게 보장합니까? 명령 아마도 onPause 메서드에 배치 된? 나는 Changwei 아래에 제안하는대로 활동을 설정 : launchMode SingleTop 매니페스트 아래에 제안했지만 원하는 효과가 없었어요. – newyorkgena

+0

카이, 내 응용 프로그램에서 고정 단어를 제거했습니다. -static. 불행히도 여전히 동일한 오류가 발생합니다. – newyorkgena

+0

activity : launchMode는 메모리 관리와 관련이 없습니다.이를 해결하려면 메모리 프로파일 링을 사용하여 메모리 누수가있는 곳을 확인해야합니다. //stackoverflow.com/questions/3112671/android-memory-analysing-eclipse-memory-analyzer and this : http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html – Kai

0

활동의 LaunchMode를 SingleTop으로 설정하십시오.

그리고 활동 onDestroy 때 리소스를 해제해야합니다. 행운을 빕니다.

+0

android : launchMode = "singleTop"를 추가 했는데도 행운을 빕니다. (매초마다 강제로 닫습니다. – newyorkgena

관련 문제