2014-02-24 20 views
0

有人可以解釋什麼是在這裏發生什麼線程被阻止?此處的線程對象用於畫布和繪圖圖形,因此將在此圖形線程上調用join()方法,以便它繼續完成。而另一個線程被阻塞並等待。哪個線程是這個?哪個線程被阻塞等待線程連接()在SurfaceView的這個簡短示例中完成?

如果surfaceView類在主UI線程上運行,那麼UI將被阻塞,等待圖形線程完成。這根本不符合邏輯。所以其他的解釋是在這裏有三個獨立的線程。主要的UI線程,join()被調用的圖形線程,以及第三個用於表面視圖的線程在圖形線程結束時被阻塞

實際上有三個線程在運行,而UI線程是不是被阻止的人?

無處在我的代碼中,我是否爲SurfaceView啓動了一個新線程。我只實例化了一個SurfaceView對象。

隨着代碼的寫入,看起來主UI線程被阻塞,等待圖形線程完成。

如果SurfaceView對象在線程或AsyncTask內部實例化,那麼它看起來更清晰。

//此代碼位於SurfaceView類

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    // can also put this code in surfaceChanged 
    running = true; 
    thread = new Thread(surfaceRunnable); 
    thread.start(); 

} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    running = false; 
    boolean retry = true; 
    while(retry) { 
     try { 
     thread.join(); 
     retry = false; 
     } catch(InterruptedException e) { 

     } 
    } 
+2

執行'thread.join()'的線程是被阻塞的線程,而不是'thread'表示的線程。 –

+0

是否意味着surfaceDestoryed被後臺線程調用,而不是主UI線程? – Kevik

+0

如果將日誌消息添加到某些代碼('surfaceCreated()','surfaceDestroyed()','surfaceRunnable.run()',然後使用'adb logcat -v threadtime'查看logcat輸出,則可以看到日誌消息旁邊的線程ID,這使得將活動映射到特定線程變得很容易。更好的辦法是附上一個調試器,然後看看所有的線程是什麼以及每個線程停止了什麼 - 然後你就會知道不僅是什麼,而且是爲什麼。 – fadden

回答

0

被阻止爲UI線程線程的內部。用調試器證明這是個好主意。您可以通過查看SurfaceView.java的源代碼來進行確認(如果在Eclipse中,則在光標位於文本SurfaceView上時點擊F3)。特別是:

surfaceDestroyed()的回調是從SurfaceView.updateWindow()稱爲:

private void updateWindow(boolean force, boolean redrawNeeded) { 
    ... 
    callbacks = getSurfaceCallbacks(); 
    for (SurfaceHolder.Callback c : callbacks) { 
     c.surfaceDestroyed(mSurfaceHolder); 
    } 

updateWindow()是從Handler衍生和分配匿名類叫mHandler

final Handler mHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
      case KEEP_SCREEN_ON_MSG: { 
       setKeepScreenOn(msg.arg1 != 0); 
      } break; 
      case GET_NEW_SURFACE_MSG: { 
       handleGetNewSurface(); 
      } break; 
      case UPDATE_WINDOW_MSG: { 
       updateWindow(false, false); 
      } break; 
     } 
    } 
}; 

注意,這mHandler對象是在構造SurfaceView對象時構建的,這發生在UI線程上。並注意Handler構造函數將Handler綁定到與當前線程(UI線程)關聯的Looper。因此handleMesssage()在該Looper上運行,這是UI線程的Looper。因此,在UI線程上調用updateWindow()

updateWindow()在文件中也被稱爲其他幾次,並且大多數時候很容易推斷出它是從UI線程調用的。