2011-12-07 10 views
11

レンダラーに別のクラスの値を渡したいとします。レンダラーが値を計算した後、ヘルパークラスにミューテックスがあり、レンダラーが計算を終了したので、私はこれらの新しい値を続けることができます。私はレンダラーに問題のない値を渡すことができますが、戻す方法を理解することはできません。私は現在いくつかの静的変数を使用していますが、レンダラによって変更された後、それらは失われているようです。彼らは私の他のクラスでは見えません。 例:レンダラーと別のクラス間の変数をqueueEvent()で渡します

public class MyRenderer implements GLSurfaceView.Renderer{ 

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

私のヘルパークラス:

私のレンダラで

クラス

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 Helper{ 

public static volatile boolean hasCalculated = false; 

} 

hasCalculatedはレンダラーでは必ずtrueに設定されていますが、他のクラスでは常にfalseと表示されます。どんな考え?私の最高の推測は、それが別のスレッドであるためですが、どうすればそれを解決できますか?よりクリーンで安全なアプローチがあれば、私は彼のことを聞いてうれしいです。

答えて

14

レンダラをアクティビティ内の変数として保持することができます(たくさんの人が行うように、MyRenderer myRenderer = new MyRenderer(); mGLView.setRenderer(myRenderer);)。それから、メソッド呼び出しを通して簡単にレンダラーと通信できます。この問題は、スレッド間通信につながります。私は以下の2つの例を挙げました.1つは非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 
    } 


} 


} 

それからちょうどGLスレッドと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 

     } 

    } 

}); 
+0

うわー、ありがとう。私は仕事に戻ったときに明日近く見ることができます。 – Lennart

関連する問題