当主要活动忙时,为什么我的Surface视图类会停止渲染?

时间:2015-06-19 19:22:01

标签: java android multithreading surfaceview

我正在为Android扩展SurfaceView实现一个简单的渲染视图类。我的主要活动类包括用于其他操作的无限循环。

然而,当主要活动处于无限循环时,应用程序显示黑屏。据我所知,主活动和表面视图类有自己独立的线程,因此即使主活动类繁忙,表面视图类也应该保持渲染。当我通过设置'运行'来防止无限循环时,该应用程序工作正常代码中的布尔变量false。

当我的主要活动处于无限循环时,表面视图类停止渲染的原因是什么?

我的主要活动和表面视图类如下:

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();
    }
}

这是我的扩展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
            }
        }
    }

}

1 个答案:

答案 0 :(得分:0)

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

不会立即显示视图。相反,它必须首先进行布局遍历,这不会立即发生,而是与Activity生命周期方法异步发生,并且它发生在主线程上。因此,在onCreate()末尾运行无限循环会阻止视图层次结构的布局遍历,这意味着您的SurfaceView将永远不会显示。

理论上,您可以尝试使用Handler开始延迟无限循环,但也可以用于实验目的。总的来说,主线程上的无限循环是一个非常糟糕的主意,除了实验之外我无法看到你想要这样做的原因。

我对这个问题的自我回答Modifying views in AsyncTask doInBackground() does not (always) throw exception详细介绍了幕后发生的事情。问题与你在这里提出的问题没有直接关系,但我认为背景是相同的。