2017-08-14 25 views
1

所以這段代碼似乎是這個問題:安卓:表面已被釋放

public void surfaceCreated(final SurfaceHolder sh) { 
    loop = new Loop(); 
    loop.setMethod(new LoopMethod() { 
     public void callMethod() { 
      Canvas canvas = sh.lockCanvas(); 
      synchronized(sh) { 
       draw(canvas); 
      } 
      sh.unlockCanvasAndPost(canvas); 
     } 
    }); 
    loop.setRunning(true); 
    loop.start(); 
} 

這工作得很好,直到用戶備份出來的應用程序,或者打開了最近的項目托盤。當我得到以下錯誤:

java.lang.IllegalStateException: Surface has already been released. 

指向這一行:

sh.unlockCanvasAndPost(canvas); 

爲什麼會發生這種情況,如何解決?

編輯:完整的疑難CLASS

public class SplashScreen extends SurfaceView implements SurfaceHolder.Callback { 
    private SplashActivity splashActivity; 
    private Loop loop; 

    //Loading gif info 
    private Movie loadingGif; 
    private long gifStart; 
    private int gifW, gifH; 
    private boolean gifDone; 

    public SplashScreen(Context context, SplashActivity splashActivity) { 
     super(context); 
     getHolder().addCallback(this); 

     this.splashActivity = splashActivity; 

     //Load gif in 
     InputStream gifStream = context.getResources().openRawResource(+ R.drawable.load); 
     loadingGif = Movie.decodeStream(gifStream); 
     gifW = loadingGif.width(); 
     gifH = loadingGif.height(); 
     gifDone = false; 
    } 

    private void beginLoading() { 

    } 

    public void surfaceCreated(final SurfaceHolder sh) { 
     loop = new Loop(); 
     loop.setMethod(new LoopMethod() { 
      public void callMethod() { 
       Canvas canvas = sh.lockCanvas(); 
       synchronized(sh) { 
        draw(canvas); 
       } 
       sh.unlockCanvasAndPost(canvas); 
      } 
     }); 
     loop.setRunning(true); 
     loop.start(); 
    } 

    public void draw(Canvas canvas) { 
     if(canvas != null) { 
      super.draw(canvas); 
      canvas.save(); 

      canvas.drawColor(Color.rgb(69, 69, 69)); 
      Paint p = new Paint(); 
      p.setAntiAlias(true); 

      long now = android.os.SystemClock.uptimeMillis(); 
      if(gifStart == 0) 
       gifStart = now; 
      if(loadingGif != null) { 
       int dur = loadingGif.duration(); 
       if(!gifDone) { 
        int relTime = (int) ((now - gifStart) % dur); 
        loadingGif.setTime(relTime); 
       } 
       else 
        loadingGif.setTime(dur); 

       if(now - gifStart > dur && !gifDone) { 
        gifDone = true; 
        loadingGif.setTime(dur); 
        beginLoading(); 
       } 

       float scaleX = getWidth()/gifW*1f; 
       float scaleY = getHeight()/gifH*1f; 
       float centerX = getWidth()/2/scaleX - gifW/2; 
       float centerY = getHeight()/2/scaleY - gifH/2; 

       canvas.scale(scaleX, scaleY); 
       loadingGif.draw(canvas, centerX, centerY, p); 
       canvas.restore(); 

       p.setColor(Color.WHITE); 
       p.setTypeface(Typeface.create("Segoe UI", Typeface.BOLD)); 
       p.setTextSize(UsefulMethods.spToPx(12)); 
       String s = "Version " + BuildConfig.VERSION_NAME; 
       canvas.drawText(s, 10, getHeight() - 10, p); 
      } 
     } 
     else 
      System.out.println("not drawing :("); 
    } 

    public void surfaceDestroyed(SurfaceHolder sh) { 
     loop.setRunning(false); 
    } 
    public void surfaceChanged(SurfaceHolder sh, int format, int width, int height) { 
     System.out.println("call"); 
    } 
} 
+0

發生這種情況,因爲你的活動不活躍了。你應該停止'onDestroy()'中的循環,並在'onResume()'中再次附加它。你嘗試過嗎? –

+0

@MatiasOlocco這不屬於Activity類。它位於一個'SurfaceView'類裏面 – Ryan

+0

不過,你使用的是表面,所以你應該在應用程序轉到背景時停止使用它,並在它返回時恢復使用。 –

回答

0

檢查知名度已經改變,如果它有暫停/恢復循環:

public void onVisibilityChanged(View view, int visibility) { 
    super.onVisibilityChanged(view, visibility); 
    if(loop != null) 
     if(visibility == VISIBLE) 
      if(!loop.isRunning()) 
       loop.setRunning(true); 
      else; 
     else if(visibility == INVISIBLE) 
      if(loop.isRunning()) 
       loop.setRunning(false); 
} 
+1

你不能只用:if(loop!= null)loop.setRunning(visibility!= VISIBLE) –

+0

@MatiasOlocco是的,這是一個更清潔的外觀。 (在縮短代碼時仍然不是最大的) – Ryan

+0

選中此答案以同步運行。除此之外,它應該可以: https://stackoverflow.com/a/25960100/3965050 –