2012-11-23 6 views
3

다시 한번 나는 도움이 필요 "비트 맵 재활용"때문에 다시 시작하면 충돌 // stackoverflow.com/questions/13511657/problems/with-big-drawable-jpg-image) 그리고 나는 스스로 해결했다. (그 질문에 대한 내 자신의 답변이다.)하지만 GLRenderer 텍스쳐로 비트 맵을 사용하면서 활동을 재개 할 때마다 충돌. 나는 많은 것들을 시도했다. 마지막 시도는 그 비트 맵을 멤버 변수로 액티비티로 유지하기 위해 비트 맵을 정적으로 만드는 것이지만, 나는 그것을 해결하기 위해 mBuffer를 잃어 버리기 때문에 충돌한다. 활동 코드에GLSurfaceView.Renderer는

자세한 내용은 :

나는 매니페스트에 SingletonInstance로 선언

android:launchMode="singleInstance" 

렌더러의 타일을 유지하기 위해.

여기에 일부 코드 : getTextures 방법에

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    mGLSurfaceView = new GLSurfaceView(this); 
    mGLSurfaceView.setEGLConfigChooser(true); 
    mSimpleRenderer = new GLRenderer(this); 

    getTextures();  

    if (!mIsTileMapInitialized){ 

     tileMap = new LandSquareGrid(1, 1, mHeightmap, mLightmap, false, true, true, 128, true); 
     tileMap.setupSkybox(mSkyboxBitmap, true); 
     mIsTileMapInitialized = true; 
    } 

    initializeRenderer(); 
    mGLSurfaceView.setRenderer(mSimpleRenderer); 

    setContentView(R.layout.game_layout); 

    setOnTouchListener(); 
    initializeGestureDetector(); 

    myCompassView = (MyCompassView)findViewById(R.id.mycompassview); 

    // Once set the content view we can set the TextViews: 
    coordinatesText = (TextView) findViewById(R.id.coordDynamicText); 
    altitudeText = (TextView) findViewById(R.id.altDynamicText); 
    directionText = (TextView) findViewById(R.id.dirDynamicText); 

    //if (!mIsGLInitialized){ 
    mOpenGLLayout = (LinearLayout)findViewById(R.id.openGLLayout); 
    mOpenGLLayout.addView(mGLSurfaceView); 
    mVirtual3DMap = new Virtual3DMap(mSimpleRenderer, tileMap); 

    if (mGameThread == null){ 
     mGameThread = new Thread(mVirtual3DMap); 
     mGameThread.start(); 
    } 

} 

내가 몇 가지 작은 텍스처 내 마지막 질문 자체의 응답으로 가장 큰 얻을 : 그래서, 다시

if (mTerrainBitmap==null){ 
     InputStream is = getResources().openRawResource(R.drawable.terrain); 
     try { 
      // Set terrain bitmap options to 16-bit, 565 format. 
      terrainBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565; 
      Bitmap auxBitmap = BitmapFactory.decodeStream(is, null, terrainBitmapOptions); 
      mTerrainBitmap = Bitmap.createBitmap(auxBitmap); 
     } 
     catch (Exception e){ 

     } 
     finally { 
      try { 
       is.close(); 
      } 
      catch (IOException e) { 
       // Ignore. 
      } 
     } 
    } 

을 처음으로 위대한 작품이지만 내가 돌아갈 때 나는 다음과 같이한다 :

protected void onPause() { 
    super.onPause(); 
    mGLSurfaceView.onPause(); 

} 
@Override 
protected void onStop() { 
    // TODO Auto-generated method stub 
    super.onStop(); 
    if (mVirtual3DMap != null) { 
     try { 
      mVirtual3DMap.cancel(); 
      mGameThread=null; 
      mVirtual3DMap = null; 
      mGLSurfaceView.destroyDrawingCache(); 
      mSimpleRenderer=null; 
      System.gc(); 
     } catch (Throwable e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

} 

그리고 나는 다시 활동을 재개한다 :

@Override 
protected void onResume() { 
    super.onResume(); 
    mGLSurfaceView.onResume(); 
    if (mVirtual3DMap != null) { 
     try { 
      mVirtual3DMap.resume(); 
     } catch (Throwable e) { 
      e.printStackTrace(); 
     } 
    } 
} 

그리고 충돌이 발생합니다.

왜 ??

java.lang.IllegalArgumentException가 : 비트 맵이 2 배 이상 원래의 활동을 시작하기 때문에

내가이 지저분한 물건을 시도 ... 재활용 응용 프로그램의 bacuse 충돌 좋아, 여기에 GLThread에 예외 원인은 이것은 또는 사용 된 메모리의 양 때문에 그리고 지금 나는이 모든 변화를 되 돌리거나 이것으로 무엇을 할 것인지 모르겠습니다.

이 응용 프로그램 활동이나 다른 응용 프로그램 활동에서 메모리에 보관할 수있는 좋은 방법이 있습니까?

제발, 당신의 조언이 필요합니다.

미리 감사드립니다.

답변

0

아니요. Android에서 모든 리소스를 처리하도록합니다. 활동이 재개 될 때 적절한 이벤트를 처리하고 비트 맵을 다시로드해야합니다. 활동을 다시 시작한 후에도 OpenGL 핸들이 유효하다는 것은 기대할 수 없습니다.

최대 절전 모드에서 나오는 노트북의 예와 같이 생각하십시오. 모든 메모리가 복원되었지만 열려있는 소켓이 여전히 실제 활성 연결을 유지할 것으로 기대할 수는 없습니다.

나는 Android noobie입니다. 그러므로 내가 틀렸다면 나를 수정하십시오.

+0

답장을 보내 주셔서 감사합니다. 당신이 맞아요. 에릭, 요점은 각 oncreate에서 OpenGL 게임 스레드를 만드는 것입니다. 그러나 텍스처 비트 맵이 많은 메모리 리소스를 소비하고 타일 계산이 게임에서 오랜 프로세서 시간을 소모하므로 게임에서 사용할 수 있도록해야합니다. 액티비티로 인해 액티비티가 일부 정적 필드가있는 단일 인스턴스로 리팩터링 된 이유입니다. 내가 메모리를 관리하기 위해 안드로이드를 떠난 경우 메모리 오류가 발생하여 충돌이 발생합니다. – JxXx

+0

Android에서 애플리케이션을 닫을 때 앱을 정말로 닫아야 할지를 결정하는 것은 운영체제입니다. 그렇다면 Android가 앱 상태를 저장하고 (나에게 메모리 덤프처럼 보임) 나중에 복원됩니다. 그래서 당신의 기억은 보존 될 것이지만, OpenGL과 그 모든 자원은 풀려날 것이고 OpenGL의 새로운 인스턴스가 이력서에로드 될 것입니다. OpenGL 외부에서 모든 타일 계산 및 텍스처를 수행 한 경우 (바이트 [] 또는 무언가로 저장) 가능합니까? 그런 다음 이력서에서 바이트 배열에서 OpenGL 텍스처를 생성합니다. 다시 계산할 필요가 없습니다. OpenGL에 대한 데이터 전송 만 가능합니다. – Eiver

2

수동으로 리소스를 처리하지 마십시오. 그렇지 않으면 앱 표면이 깨집니다. 리소스를 수동으로 처리 할 수는 없습니다.

리소스를 다시로드하는 데 문제가 있고 API 레벨 11 이상을 사용하는 경우 setPreserveEGLContextOnPause()을 사용할 수 있습니다. 텍스처와 FBO를 보호합니다.

API 11+를 사용할 수없는 경우 GLSurfaceView()을 앱에 포트 할 수 있습니다. ICS에서 이식 된 my own GLSurfaceView을 확인할 수 있습니다.

추신 : 불쌍한 영어에 대해 죄송합니다.

+0

기회를 주겠다. setPreserveEGLContextOnPause를 시도하고 GLSurfaceView를 다시 만들지 말고 보존 할 수 있습니다. 영어에 대해 걱정하지 마십시오, 저는 스페인 출신이며 동일한 문제가 있습니다. 인사말. – JxXx

+0

전진 했습니까? – Dalinaum

+0

죄송합니다 Dalinaum, 나는 아직 그 시도를하지 않았지만 그것이 내 대답이라고 들립니다. 이 workarround 내 인생 TODO 목록에 있지만 내가 다루고있어 매우 나쁜 일이 있었고 나는 이것에 대해 언제든지 보낼 수 없습니다. 나는 그것을 시도 할 때마다 내 대답을 갖겠지만, 나를 믿어.하지만 미리 감사드립니다. – JxXx