SurfaceView因為獨特的雙緩衝機制,在android應用中十分普遍,視訊播放器、攝像機預覽等都會用到,如果在兩個Fragment或者一個Fragment和Activity同時使用都會造成無法正常顯示。即使設定前面的SurfaceView為不可見也會在少部分機型上依然存在該問題。後來發現原因是SurfaceView是在Windows層顯示的,僅僅用View層的方法並不能控制Surface的生命週期。

解決辦法:在需要播放視訊的位置外層巢狀一個Layout,這裡我用的Framelayout,在釋放的時候使用removeAllViews直接釋放SurfaceView和他的Surface物件,下面程式碼:

  1. /**
  2. * 釋放資源
  3. */
  4. private void release() {
  5. if (mSurfaceView != null && mSurfaceView.getHolder() != null && mSurfaceView.getHolder().getSurface() != null) {
  6. mSurfaceView.getHolder().getSurface().release();
  7. if (mSurfaceHolder != null && mEquipmentVideoCallBack != null) {
  8. mSurfaceHolder.removeCallback(mEquipmentVideoCallBack);
  9. mSurfaceHolder = null;
  10. }
  11. }
  12. parentLayout.removeAllViews();
  13. }

需要注意的是,只要介面不在前臺或者失去焦點的時候都需要釋放一次,還有每次重新播放前也需要釋放一次,重新進入準備狀態。

  1. //第1:顯示個隱藏的時候
  2. @Override
  3. public void onHiddenChanged(boolean hidden) {
  4. super.onHiddenChanged(hidden);
  5. release();
  6. }
  7. //第2:從新獲取焦點到前臺
  8. @Override
  9. public void onResume() {
  10. super.onResume();
  11. release();
  12. }
  13. //第3:在類似視訊播放器功能的時候一個視訊播放完也需要釋放