通过渲染器和其它类queueEvent之间的变量() [英] Pass variables between renderer and another class with queueEvent()

查看:162
本文介绍了通过渲染器和其它类queueEvent之间的变量()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过我的渲染器从另一个类中的值。经过渲染器计算出的值,我有一个辅助类,应该告诉我,渲染器已完成计算这样我就可以继续使用这些新的值互斥。我可以通过渲染器的数值没有问题,但我不知道如何让他们回来。我目前使用的一些静态变量,但之后便被渲染变化,他们似乎迷失。他们是不是在我的其它类可见。 例如:

I want to pass my renderer some values from another class. After the renderer has calculated the values, I have a mutex in a helper class that should tell me that the renderer has finished calculating so I can continue with these new values. I can pass the renderer the values without problems, but I can't figure out how to get them back. I currently use some static variables, but after they are changed by the renderer, they seem to get lost. They aren't visible in my other class. Example:

public class View extends SurfaceView{

  private void doSomething(){

     glSurfaceView.queueEvent(new Runnable() {

                @Override
                public void run() {
                  //..
                  renderer.calculate(stack);    
                }
    });
  }

private void doAnotherThing(){

    //Never happens:
    if(Helper.hasCalculated){
    /...
    }
}

}

在我的渲染

public class MyRenderer implements GLSurfaceView.Renderer{

    private void calculate(Stack stack){         
      Helper.hasCalculated = true
    }
}

我的助手类:

public class Helper{

 public static volatile boolean hasCalculated = false;

}

hasCalculated绝对是设置为true的渲染,但我的其他类始终认为这是错误的。知道为什么吗?我最好的猜测是,这是因为它在另一个线程,但我将如何解决?如果有一个更清洁,更安全的做法,我会很高兴听到他。

hasCalculated is definitely set to true in the renderer, but my other class always sees it as false. Any idea why? My best guess is that it's because its in another thread, but how would I solve that? If there is a cleaner and safer approach, I'd be happy to hear him.

推荐答案

您可以留住你的渲染器作为一个变量在你的活动(不只是做 mGLView.setRenderer(新MyRenderer() ); 作为一个很多人做,而是 MyRenderer myRenderer =新MyRenderer(); mGLView.setRenderer(myRenderer); )。然后,你可以用你的渲染很容易地通过方法调用进行通信。然后的问题仅仅归结为跨线程通信。我已经把下面的两个例子,一个具有非UI线程,GL线程和主UI线程之间的通信。第二个例子是只为GL线程和UI线程

You can keep hold of your renderer as a variable in your activity (don't just do mGLView.setRenderer(new MyRenderer()); as a lot of people do, but rather MyRenderer myRenderer = new MyRenderer(); mGLView.setRenderer(myRenderer);). Then you can communicate with your renderer easily through method calls. The problem then just comes down to cross-thread communication. I've put two examples below, one with communication between a non-UI thread, the GL thread and the main UI thread. The second example is just for communication between the GL thread and UI thread

public class Test3D extends Activity{

private MyRenderer renderer; // keep hold of the renderer as a variable in activity
private MyAsyncTask gameLoop;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    myRenderer = new MyRenderer(); // create the renderer object

    GLSurfaceView mGLView = (GLSurfaceView)findViewById(R.id.glsurfaceview1);
    mGLView.setEGLConfigChooser(true);
    mGLView.setRenderer(myRenderer); // set the surfaceView to use the renderer

    gameLoop = new MyAsyncTask(); 
    gameLoop.execute(); // start a new, non-UI, thread to do something

}

/// non-UI thread (inner class of my Test3D activity)
class MyAsyncTask extends AsyncTask<Void, Void, Void>{

    @Override
    protected Void doInBackground(Void... arg0) {

            myRenderer.startCalc(); // tell renderer to start calculation

            while(!myRenderer.isFinishedCalc()){

                // waiting for calc to finish, but not blocking UI thread

                try {
                    long x = 1000;
                    Thread.sleep(x);
                    // sleep the thread for x amount of time to save cpu cycles
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

            publishProgress(null); 
            // when calculation has finished, we will drop out of the loop
            // and update the UI



   }

    protected void onProgressUpdate(Void... progress) {         
        // update UI
    }


}


}

然后在渲染

public class MyRenderer implements Renderer{

    private boolean startCalc = false;
    private boolean finishCalc = false;

    public void startCalc(){
        finishCalc = false;
        startCalc = true;
    }

    public boolean isFinishedCalc(){
        return finishCalc;
    }

    public void onDraw(GL10 gl){

        if(startCalc){
            // do calculation using GL handle
            // always performed in the GL thread

            finishCalc = true;
            startCalc = false;
        }

        // draw

    }



}

我在渲染器实例中使用上面的标志,但它是相当简单的把它转换成一个队列,如果说,你想告诉渲染器负荷模型此阵。既然你已经使用GL手柄加载模型(或至少纹理)在GL线程,你可以有其他类和线程做你的逻辑和刚才的GL东西在GL线程中完成

I've used flags in the renderer example above, but it would be fairly simple to turn that into a queue, if, say, you wanted to tell the renderer "load this array of models". Since you have to load the models (or at least textures) in the GL thread using the GL handle, you can have other classes and threads do your logic and have just the GL stuff done in the GL thread



或者,如果你只是想更新UI线程的计算完成后,而不是与任何其他线程交互:



Alternatively, if you just want to update the UI thread after your calculation is done, rather than interact with any other threads:

public class MyRenderer implements Renderer{

    private Handler handler = null;
    public static final int CALC_FINISHED = 1;

    public void startCalc(Handler handler){
        this.handler = handler;
    }

    public void onDraw(GL10 gl){

        if(handler!=null){
            // do calculation using GL handle
            int flag = MyRenderer.CALC_FINISHED;
            handler.dispatchMessage(Message.obtain(handler, flag));
            // adds a message to the UI thread's message queue

            handler = null;

        }

        // draw

    }

}

,然后从任何地方:

and then from anywhere:

myRenderer.startCalc(new Handler(){

    public void handleMessage (Message msg){

        if(msg.what==MyRenderer.CALC_FINISHED){
            // Update UI
            // this code will always be executed in the UI thread

        }

    }

});

这篇关于通过渲染器和其它类queueEvent之间的变量()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆