当前位置: 首页 > 面试题库 >

使用queueEvent()在渲染器和另一个类之间传递变量

姬高澹
2023-03-14
问题内容

我想将其他类的一些值传递给渲染器。渲染器计算出值之后,我在帮助器类中有了一个互斥锁,该互斥体应该告诉我渲染器已完成计算,因此我可以继续使用这些新值。我可以毫无问题地传递渲染器的值,但是我不知道如何找回它们。我目前使用一些静态变量,但是在渲染器更改它们之后,它们似乎丢失了。它们在我的其他课程中不可见。例:

一类

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,但是我的其他类始终将其视为false。知道为什么吗?我最好的猜测是这是因为它在另一个线程中,但是我该如何解决呢?如果有更清洁,更安全的方法,我很高兴听到他的声音。


问题答案:

您可以在活动中将渲染器作为变量保存(不像mGLView.setRenderer(new MyRenderer());很多人那样,而是MyRenderer myRenderer = new MyRenderer(); mGLView.setRenderer(myRenderer);)。然后,您可以通过方法调用轻松地与渲染器进行通信。然后问题就归结为跨线程通信。我在下面放置了两个示例,一个示例用于非UI线程,GL线程和主UI线程之间的通信。第二个示例仅用于GL线程和UI线程之间的通信

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的工作

另外,如果您只想在完成计算后更新UI线程,而不是与任何其他线程进行交互:

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

    }

}

然后从任何地方:

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

        }

    }

});


 类似资料:
  • 问题内容: 我想将一个类变量传递给另一个类,并使其成为该类的类变量。在以下情况下我该怎么做? 问题答案: 很难理解您正在问的问题,但这是一个可能的答案: 使B类成为A的子类: 如果重新声明为,则会出现一种情况,其中存在一个可以称为或的属性。(或在任一或刚刚…甚至作为或地方,并有类型和分别。) 如果您无法在和(或,以及一些包含声明的第三类)之间创建直接或子类型关系,那么您很不走运。他们无法共享声明。

  • 我得到了这个错误: “变量'a'已赋值,但其值永远不可用”

  • 我有两个班级。首先是MainActivity.kt,我有一些字符串。第二个是像这样的ServiceBuilder.kt 我需要正确地将字符串从 MainActivity 传输到此对象。我认为在ServiceBuilder中创建MainActivity对象不是一个好主意,因为它分配了多余的内存。使用数据库或共享首选项也不是一个好主意,因为这种调用会减慢工作程序的速度,并且这种技术是为解决其他问题而创

  • 从节点(express)服务器端渲染时,我无法将初始道具传递到我的React组件 以下是我的组件的简短版本: 这是服务器端 在render()方法中尝试使用组件时,prop似乎没有传递给组件 有什么想法吗?

  • 我有一个JPanel表单,其中包含一个JList和一些JButton。JPanel看起来像这样 当我单击Add List按钮时,会显示一个单独的JFrame表单。JFrame表单将如下所示 单击JFrame上的add按钮时,我需要将JTextfield(命名列表名)的值添加到上一个JPanel上的JList。我想知道如何将值从JFrame传递到JPanel?如有任何建议,将不胜感激。 下面是 JP

  • 我尝试了几乎所有可用的解决方案,但似乎都不起作用我需要在两个Javafx场景之间传递,但当我单击以导航到下一个场景时,什么也没有发生。以下是我目前为止的代码: