2013-05-20 46 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! –