2011-11-07 40 views
0

我有一個線程問題,我的surfaceView,它很常見,但我沒有找到任何解決方案。SurfaceView從另一個活動返回時崩潰

我使用SurfaceView作爲一個框架佈局的背景:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/blobmusic_layout" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 

    <com.myapp.Background 
    android:id="@+id/background_blobmusic" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"/> 
    ... 

和我的背景類是tipical surfaceview類,與支架,線程至極會調用我們的onDraw方法等,有些代碼避免問題(的init()被調用構造方法):

public void init() { 
    ready = false; 
    holder = getHolder(); 
    holder.addCallback(new Callback() { 

     @Override 
     public void surfaceDestroyed(SurfaceHolder holder) { 
      // TODO Auto-generated method stub 
      boolean retry = true; 
      while (retry) { 
       try { 
        bgdt.setRunning(false); 
        bgdt.join(); 
        retry = false; 
       } catch (InterruptedException e) {} 
      } 
     } 

     @Override 
     public void surfaceCreated(SurfaceHolder holder) { 
      // TODO Auto-generated method stub 
      holder.setFormat(PixelFormat.RGBA_8888); 
      estrelles = new Estrelles(getResources(),getHeight()); 
      bgdt.setRunning(true); 
      bgdt.start(); 
      ready = true; 
     } 

     @Override 
     public void surfaceChanged(SurfaceHolder holder, int format, int width, 
       int height) { 
      // TODO Auto-generated method stub 

     } 
    }); 

和我的線程類(bgtd):

public class BGDrawThread extends Thread { 
private Background view; 
static final long FPS = 60; 
private boolean running = false; 

public BGDrawThread(Background view) { 
     this.view = view; 
} 

public boolean isRunning() { 
    return running; 
} 

public void setRunning(boolean run) { 
     running = run; 
} 

@Override 
public void run() { 
    long ticksPS = 1000/FPS; 
    long startTime; 
    long sleepTime; 
    //fps checker 
    long contms=0; 
    long lasttimecheck = System.currentTimeMillis(); 
    int fps=0; 
    while (running) { 
     if(contms>1000) { 
      //souts ?? 
      contms=0; 
      fps=0; 
      lasttimecheck = System.currentTimeMillis(); 
     } 
     else { 
      fps++; 
      contms+=System.currentTimeMillis()-lasttimecheck; 
      lasttimecheck=System.currentTimeMillis(); 
     } 
     Canvas c = null; 
     startTime = System.currentTimeMillis(); 
     try { 
      c = view.getHolder().lockCanvas(); 
      synchronized (view.getHolder()) { 
       view.onDraw(c); 
      } 
     } finally { 
      if (c != null) { 
       view.getHolder().unlockCanvasAndPost(c); 
      } 
     } 
     sleepTime = ticksPS-(System.currentTimeMillis() - startTime); 
     try { 
      if (sleepTime > 0) 
        sleep(sleepTime); 
      else 
        sleep(10); 
    } catch (Exception e) {} 
    } 
} 
} 

這工作正常,直到另一個活動前面,然後我們從它回來,那崩潰。

這裏是我的類的onPause /的onResume方法的代碼:

@Override 
protected void onResume() { 
    super.onResume(); 
    Background bmbg = (Background) findViewById(R.id.background_blobmusic); 
    bmbg.resumethread(); 
} 
@Override 
protected void onPause() { 
    super.onPause(); 
    Background bmbg = (Background) findViewById(R.id.background_blobmusic); 
    bmbg.stopthread(); 
} 

,並在surfaceview類滑索/恢復線程:

public void stopthread() { 
    if(!bgdt.isAlive()) return; 
    boolean retry = true; 
    while (retry) { 
     try { 
      bgdt.setRunning(false); 
      bgdt.join(); 
      retry = false; 
     } catch (InterruptedException e) {} 
    } 
} 
public void resumethread() { 
    if(ready && !bgdt.isRunning()) { 
     bgdt.setRunning(true); 
     bgdt.start(); 
    } 
} 

所有幫助都是歡迎的。

編輯:我讓它運行(可能不是一個優雅的解決方案,但我離開代碼在這裏): (看看下面的評論,看看其他的變化)

public void startthread() { 
    if(!surfacecreated) return; 
    if(threadrunning) return; 
    bgdt = new BGDrawThread(this); 
    bgdt.setRunning(true); 
    bgdt.start(); 
    threadrunning = true; 
} 

public void stopthread() { 
    boolean retry = true; 
    while (retry) { 
     try { 
      bgdt.setRunning(false); 
      bgdt.join(); 
      threadrunning = false; 
      retry = false; 

     } catch (InterruptedException e) {} 
    } 
} 

回答

0

IIRC表面準備操作後,才surfaceChanged()的回調,而不是surfaceCreated(),和surfaceChanged()是的onResume()之後調用 - 將你的初始化和線程啓動有(以surfaceChanged())

+0

好吧,它不起作用。它甚至在我看到任何主要活動之前崩潰。任何其他想法? – Carles

+0

經過一段時間做了一些測試和一些研究,我發現究竟發生了什麼。 SurfaceChanged僅在調用onStop()時調用,而不是在onPause()之後調用。從這裏我設置了一對控制變量,surfacecreated和threadrunning,並且在我的onStart和onResume方法中調用startthread(),並在我的onPause onResume方法中調用stopthread()。另外startthread()由surfacecreated調用。 我的功能是:(主要職位編輯部分)。 – Carles

相關問題