1

I am implementing a simple render view class for Android extending SurfaceView. My main activity class includes an infinite while loop for other operations.

However, the app shows a black screen when main activity is in the infinite loop. As far as I know, main activity and surface view classes have their own separate threads, so surface view class should keep rendering even when main activity class is busy. The app works just fine when I prevent infinite loop by setting 'running' boolean variable false in the code.

What might be the reason of that surface view class stops rendering when my main activity is in an infinite loop?

My main activity and surface view classes are as follows:

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity{
    RenderSurfaceView renderView;

    public boolean running = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate ( savedInstanceState );
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        renderView = new RenderSurfaceView(this);
        setContentView(renderView);

        loop();
    }

    public void loop(){
        running = true;
        while(running){

        }
    }

    protected void onResume() {
        super.onResume();
        renderView.resume();
    } 

    protected void onPause() {
        super.onPause();
        renderView.pause();
    }
}

This my render class that extends SurfaceView:

import java.util.Random;

import android.content.Context;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class RenderSurfaceView extends SurfaceView implements Runnable{
    Thread renderThread = null;
    SurfaceHolder holder;
    volatile boolean running = false;

    Random r = new Random();

    public RenderSurfaceView(Context context) {
        super(context);
        holder = getHolder();

    }

    public void resume() {
        running = true;
        renderThread = new Thread(this);
        renderThread.start();
    }

    public void run() {
        while(running) {
            if(!holder.getSurface().isValid())
                continue;
            render();
        }
    }

    private void render(){
        Canvas canvas = holder.lockCanvas();

        canvas.drawRGB(r.nextInt(255), r.nextInt(255), r.nextInt(255));

        holder.unlockCanvasAndPost(canvas);
    }

    public void pause() {
        running = false;
        while(true) {
            try {
                renderThread.join();
            } catch (InterruptedException e) {
                // retry
            }
        }
    }

}
  • You have your view implement a runnable, but you don't ever call the `run` method to start execution in a separate thread. Try calling `run` – JustWannaFly Jun 19 '15 at 19:25

1 Answers1

0

This

renderView = new RenderSurfaceView(this);
setContentView(renderView);

does not show the view immediately. Instead it has to go through a layout traversal first, which doesn't happen immediately but asynchronously to the Activity lifecycle methods, and it happens on the main thread. So running an infinite loop at the end of onCreate() prevents the layout traversal of the view hierarchy, which means your SurfaceView will never be shown.

In theory you could experiment with starting your infinite loop delayed using a Handler, for experimental purposes maybe. In general infinite loops on the main thread are a super bad idea and I can't see a reason why you would want to do this, apart from experiments maybe.

My self-answer to this question Modifying views in AsyncTask doInBackground() does not (always) throw exception has a bit more detail on what's going on behind the scenes. The question is not directly related to what you're asking here, but the background is the same I believe.

Community
  • 1
  • 1
ci_
  • 8,594
  • 10
  • 39
  • 63
  • Aside from `Main Activity` and `SurfaceView`, should I utilize another thread for game logic loop such as state changes, physics engines etc.? [Is a separate thread for game loop compulsory for simple games?](http://gamedev.stackexchange.com/questions/71911/is-a-separate-thread-for-game-loop-compulsory-for-simple-games) discusses this issue and suggests that game logic loop can be included in the main thread. – acyuzuguler Jun 19 '15 at 19:56
  • Yeah, it says you can do it in the main thread if you're not doing anything "too intense". An infinite loop by definition is very intense. – ci_ Jun 19 '15 at 20:02
  • You could use a `Handler`/`Runnable` combination to implement this on the main thread. – ci_ Jun 19 '15 at 20:03
  • Some additional recommended reading: https://source.android.com/devices/graphics/architecture.html#activity and https://source.android.com/devices/graphics/architecture.html#loops – fadden Jun 19 '15 at 20:09