Why is my constructor/Renderer class being called twice?

Started by
8 comments, last by grumpyOldDude 8 years, 10 months ago

Hello

Initially things were being rendered correctly. But then i soon noticed some mis-matches in objects rendered. I wasn't aware exactly when it started that way,

but when i started tracing data... I realised its because my renderer constructor is called twice , because the data printouts of all function-calls within the renderer constructor print out twice. But i only called it once

In fact i think all funtion-calls within the renderer class are called twice because when i moved the function-calls to onDrawFrame(GL10 gl) same problem occured


public class MyGLSurfaceView  extends GLSurfaceView {
	public int n = 16,   t=0, r=0;
	
	public MyGLSurfaceView(Context context, AttributeSet attrs ) {
		
		super(context, attrs);
			     
		setRenderer(new MyGLRenderer(context, n, t ));  // renderer called once
	
	}

}

public class MyGLRenderer implements GLSurfaceView.Renderer {
       Context context;   // Application's context
       
       private mObjects  Objs;    
     
       public MyGLRenderer(Context context, int NumOfData, int dataType ) {  // implemented once
       
      Objs = new mObjects( NumOfData, dataType ); 
      Objs.customAxesWBL();
      Objs.customAxesBL();
      Objs.callByteBufferLoop(NumOfData);
  }
   .....

To get my renderer outputs right now i have to place the if statement below around all code within the affected functions so the algorithms run just once. Then the output was fixed. But why should i have to put such ugly if statement around the algorithms?


if ( Globals.customAxesBL_Once == 0 ){
       Globals.customAxesBL_Once = 1;

......
}

Anyone experienced this before? Whats the cause? Any way to fix it?

Many thanks

can't help being grumpy...

Just need to let some steam out, so my head doesn't explode...

Advertisement

In such a case: Set a breakpoint and run the program in debug mode. When the debugger stops, then look at the object-id of "this" and at the call stack. When after continuing the debugger stops a second time, look again at the object-id and compare it with the one before, and again look at the call stack. Use the call stacks to realize which functions have caused the invocations.

Also can you show the implementation of setRenderer because I am expecting to find the error in the implementation there to be honest. If you are storing a list of renderers this is simple to mess up.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion


    super(context, attrs);

Is it possible that a MyGLRenderer is already initialized once during this call fom the MyGLSurfaceView constructor?

Also can you show the implementation of setRenderer because I am expecting to find the error in the implementation there to be honest. If you are storing a list of renderers this is simple to mess up.

I couldn't since setRenderer() is an Android system call:

void android.opengl.GLSurfaceView.setRenderer(Renderer renderer)

Set the renderer associated with this view. Also starts the thread that will call the renderer, which in turn causes the rendering to start.
This method should be called once and only once in the life-cycle of a GLSurfaceView.
The following GLSurfaceView methods can only be called before setRenderer is called


Is it possible that a MyGLRenderer is already initialized once during this call fom the MyGLSurfaceView constructor?

I think that would throw an exception. Actually the whole of the MyGLSurfaceView constructor is in the OP . I'm thinking, maybe its a system bug wub.png

can't help being grumpy...

Just need to let some steam out, so my head doesn't explode...


I'm thinking, maybe its a system bug

Although that's possible, it's also improbable. Experience shows that it is often a piece of the own software apart from the obvious places.

What does the debugger (or a manually requested stack trace) say?

View constructors can be called *a lot* on Android. For example, configurations changes (such as rotating your device from portrait to landscape) cause the entire view stack to be torn down and recreated. I'd trace through the View constructor that is calling setRenderer(), and make absolutely sure it is only being called once.

A very handy tool for figuring this stuff out are the android.log.Log functions. There are overloads which take a Throwable as a final argument, and those will print a stack trace for you:


import android.log.Log;
 
Log.e("MyGLSurfaceView", "Constructor called", new Throwable());

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Is there no way to set a breakpoint in the debugger and see where the constructor is being called from? I see the suggestion was made in the 2nd post, but no indication from the OP that this has been tried. It should only take a few seconds, and be a large step towards solving your mystery. I've never done Android development, but I'd be surprised if this were not possible.


To get my renderer outputs right now i have to place the if statement below around all code within the affected functions so the algorithms run just once. Then the output was fixed. But why should i have to put such ugly if statement around the algorithms?

Because you have global state being access from instance objects. Doesn't global state suck?

View constructors can be called *a lot* on Android. For example, configurations changes (such as rotating your device from portrait to landscape) cause the entire view stack to be torn down and recreated. I'd trace through the View constructor that is calling setRenderer(), and make absolutely sure it is only being called once.

What swiftcoder says is very very true here

When your screen changes orientation or your activity gets paused, your OpenGL context is destroyed and recreated.

Actually when the screen orientation changes IIRC the whole activity gets destroyed and recreated

Personally I would follow haegarrs advice and set a break point. Place it on the first line of the onCreate method that you override, that way you can step through from the beginning of your apps creation.

In such a case: Set a breakpoint and run the program in debug mode. When the debugger stops, then look at the object-id of "this" and at the call stack. When after continuing the debugger stops a second time, look again at the object-id and compare it with the one before, and again look at the call stack. Use the call stacks to realize which functions have caused the invocations.

What does the debugger (or a manually requested stack trace) say?

Sorry day job and sleep got in the way of a quick reply

The problem is knowing where to set the break points. If the program breaks somewhere or throws an exception that would be straight forward. But even without the "fix if statements" there is no errors or no exception thrown. Except that when its called twice variables default back original values.

What i mean in very simplified form is: for instance if a = 10, b = 0, - initial values

b = some result ( ie 5)

c = a + b

on the first call c = 15,

but on the second call it defaults back to c = 10.

so the (corrective but ugly) if statement prevents the second call and c remains 15

I agree it might be something wrong with my code but its very difficult to track down - except if i'm missing something here

View constructors can be called *a lot* on Android. For example, configurations changes (such as rotating your device from portrait to landscape) cause the entire view stack to be torn down and recreated. I'd trace through the View constructor that is calling setRenderer(), and make absolutely sure it is only being called once.

A very handy tool for figuring this stuff out are the android.log.Log functions. There are overloads which take a Throwable as a final argument, and those will print a stack trace for you:

yeah I did rotate to landscape

Personally I would follow haegarrs advice and set a break point. Place it on the first line of the onCreate method that you override, that way you can step through from the beginning of your apps creation.

Ah good hint to what i raised few lines above - knowing where to place the break point. - OnCreate()

Would try that now, if i get a fix i will post for benefit of anyone else who might encounter similar

can't help being grumpy...

Just need to let some steam out, so my head doesn't explode...

This topic is closed to new replies.

Advertisement