2013-05-20 77 views
1

我正在使用OpenGL ES的應用程序,我試圖在啓動應用程序邏輯之前將紋理加載到內存中。我嘗試了一些解決方案,但都沒有成功。Android OpenGLES在GLThread中加載紋理,然後告訴UI線程運行方法

我的動態創建代碼。 我的活動:

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

     // Create a GLSurfaceView instance and set it 
     // as the ContentView for this Activity. 
     view = new GLSurfaceView(this); 

     // Initiate the game renderer 
     renderer = new AppRenderer(this); 

     view.setRenderer(renderer); 
     // Only render when we tell it to 
     view.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 

     // Set the custom renderer as our view 
     setContentView(view); 

     startApplication(); 
    } 

上面的代碼使用錯誤,我加載紋理我AppRenderers onsurfacechanged功能。問題是startApplication()在onsurfacechanged之前運行,導致startapplication()運行時綁定的紋理不能加載並顯示白色。

我知道opengles會在它自己的線程上運行。

所以我嘗試使用下面的異步任務和標誌示例。

public class loadTextureTask extends AsyncTask<Void, Void, Boolean> { 
    @Override 
    protected Boolean doInBackground(Void... params) { 
     textureLoad = renderer.getTextureLoaded(); 
     while (textureLoad == false) { 
      textureLoad = renderer.getTextureLoaded(); 
     } 
     startApplication(); 
    } 
} 

後,我只是取代了「startApplication()」在OnCreate發起這個異步任務,所以當紋理加載了,我可以檢查。

loadTextureTask = new loadTextureTask(); 
    loadTextureTask.execute((Void) null); 

這引起以下錯誤「線程ID = 14:螺紋與未捕獲的異常(組= 0x40de82a0) 退出」和需要更多的時間用這種方法加載紋理大約20倍,只要它會加載如果這個異步任務不存在..

我想完成的是在紋理加載後運行startApplication()方法。

注:我的紋理是2

所有電源任何幫助將不勝感激!先謝謝你。

+0

將'Thread.Sleep(100);'放入while循環(壞的解決方案,但應該有所幫助)...更好的解決方案是:添加監聽器(fx:'ITextureLoaddedListener'和'done'方法)渲染器然後執行這個監聽程序在'done'方法中調用'startApplication'並在程序加載所有紋理後調用方法'done'完成監聽程序(當你將_textureLoaded標誌設置爲true時)# – Selvin

+0

嗨Selvin謝謝你的回答,你能詳細說明這個方法? –

回答

0

自第二個線程調用renderer.getTextureLoaded()以來,它需要20倍以上的時間。一次又一次,這使用了很多的CPU ... ... - 這樣你就可以做到這一點,如:

創建界面:在AppRenderer添加(variant I.

interface ITextureLoaddedListener { 
    void done(); 
} 

ITextureLoaddedListener _listener = null; 
public void setTextureLoaddedListener(ITextureLoaddedListener listener) { 
    _listener = listener; 
} 

AppRenderervariant II.)構造函數添加

public AppRenderer(Context ctx, ITextureLoaddedListener listener){ 
    _listener = listener; 
    //rest of old code 
    LoadTexturesAsync(); 
} 

爲兩個版本添加:

public void LoadTexturesAsync() { 
    new AsyncTask<Void,Void, Void>(){ 
     @Override 
     protected Void doInBackground(Void... params) 
     { 
      //do your loading texture stuff here 
      return null; 
     } 
     @Override 
     protected void onPostExecute(Void result) { 
      if(_listener!=null){ 
       _listener.done(); 
      } 
     } 

    }.execute(); 
} 

然後讓你的Activity impements ITextureLoaddedListener和實施應該是這樣的:

public YourActivity extends Activity implments ITextureLoaddedListener{ 
    //.... 
    //rest of YourActivity code 
    //.... 

    @Override 
    protected void done() 
    { 
     startApplication(); 
    } 
} 

下一個代碼添加到onCreateActivity的:

renderer = new AppRenderer(this); //or (for II.) renderer = new AppRenderer(this, this); 
renderer.setTextureLoaddedListener(this); //(for I.) no need for this if you choose II. variant 
renderer.LoadTexturesAsync();//(for I.) no need for this if you choose II. variant 
view.setRenderer(renderer); 

I. variant你不應該叫LoadTexturesAsync在構造函數AppRenderer因爲在這個地方你沒有設置監聽器。

+0

感謝您的迅速答覆Selvin,實際的圖像加載代碼在onsurfacechanged中完成,因爲它將紋理加載到內存中,並且可以訪問gl對象,異步任務無法訪問gl對象,因此無法將圖像加載到冰川 –

+0

好的,然後把LoadTexturesAsync代碼onsurfacechanged – Selvin

+0

完美的工作謝謝你的幫助Selvin! –