java - 为什么当主 Activity 繁忙时我的 Surface View 类会停止渲染?

标签 java android multithreading surfaceview

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

但是,当主要 Activity 处于无限循环中时,应用程序会显示黑屏。据我所知,主 Activity 和表面 View 类有自己单独的线程,因此即使主 Activity 类繁忙,表面 View 类也应该保持渲染。当我通过在代码中设置“running” boolean 变量 false 来防止无限循环时,该应用程序运行得很好。

当我的主要 Activity 处于无限循环中时,表面 View 类停止渲染的原因可能是什么?

我的主要 Activity 和表面 View 类如下:

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
            }
        }
    }

}

最佳答案

这个

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

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

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

我对这个问题的 self 回答Modifying views in AsyncTask doInBackground() does not (always) throw exception有更多关于幕后发生的事情的细节。这个问题与您在这里问的问题没有直接关系,但我相信背景是相同的。

关于java - 为什么当主 Activity 繁忙时我的 Surface View 类会停止渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30945794/

相关文章:

ios - 与核心音频线程同步

java - 如果子线程在调用get方法之前完成,则Java如何维护将来的任务结果

java - 如何发送请求并进行响应,并返回给客户端?

java - 如何使用 Java 为 Android 应用程序读取或写入 MySQL cPannel 数据库中的数据

java - 使用 AnnotationConfigApplicationContext 时禁用 Spring 日志记录

java - 如何确保我的应用程序不与其他使用 nfc 的应用程序冲突

Android 处理 ListView 中的许多 EditText 字段

java - 如何在Java中减去两个列表/数组的值?

java - Android Studio EditText 字段给出 null 或 0

java - ExecutorService如何改变调度时钟