GLSurfaceView布局内使用报空指针问题
博客专区 > march_kk 的博客 > 博客详情
GLSurfaceView布局内使用报空指针问题
march_kk 发表于7个月前
GLSurfaceView布局内使用报空指针问题
  • 发表于 7个月前
  • 阅读 38
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

<android.opengl.GLSurfaceView
        android:id="@+id/gls_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

1.异常

崩溃日志

java.lang.NullPointerException
  at android.opengl.GLSurfaceView.surfaceCreated(GLSurfaceView.java:531)
  at android.view.SurfaceView.updateWindow(SurfaceView.java:601)
  at android.view.SurfaceView.access$000(SurfaceView.java:94)
  at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:183)

(备注:GLSurfaceView属于framework层,有些厂商是定制的,与标准的sdk代码会有些不同。)

找到GLSurfaceView的崩溃的那一行(实际位置GLSurfaceView.Java:522)

   public void surfaceCreated(SurfaceHolder holder) {
        mGLThread.surfaceCreated();
    }

 

既然是空指针异常,显然mGLThread对象为空。

由此,找到mGLThread初始化的地方

 

  public void setRenderer(Renderer renderer) {
        checkRenderThreadState();
        if (mEGLConfigChooser == null) {
            mEGLConfigChooser = new SimpleEGLConfigChooser(true);
        }
        if (mEGLContextFactory == null) {
            mEGLContextFactory = new DefaultContextFactory();
        }
        if (mEGLWindowSurfaceFactory == null) {
            mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
        }
        mRenderer = renderer;
        mGLThread = new GLThread(mThisWeakRef);
        mGLThread.start();
    }

 

发现mGLThread是在渲染器设置的时候进行初始化

顺便再来看看GLSurfaceView的构造函数

 

 /**
     * Standard View constructor. In order to render something, you
     * must call {@link #setRenderer} to register a renderer.
     *(这里已经提示我们,必须先设置一个渲染器)
     */
    public GLSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

 

原来是画面加载的时候去调用渲染,但是布局里面没有设置渲染器所以就崩了。

2.使用

网上常见的GLSurfaceView使用方法

 ...
    GLSurfaceView mGLView = new GLSurfaceView(this); 
    mGLView.setRenderer(new DemoRenderer()); 
    //设置渲染器,其中DemoRenderer实现GLSurfaceView.Renderer

    setContentView(mGLView);
    ...

 

如果实在想在布局里使用的话,用DemoGLSurfaceView继承GLSurfaceView 
构造函数里面设置好适配器。

DemoGLSurfaceView.java

 


package test.com.asproject;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.MotionEvent;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * Created by Seselin on 2016/4/1.
 */
public class DemoGLSurfaceView extends GLSurfaceView {
    DemoRenderer mRenderer;

    public DemoGLSurfaceView(Context context) {
        super(context);
        //为了可以激活log和错误检查,帮助调试3D应用,需要调用setDebugFlags()。
        this.setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
        mRenderer = new DemoRenderer();
        this.setRenderer(mRenderer);
    }

    public DemoGLSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //为了可以激活log和错误检查,帮助调试3D应用,需要调用setDebugFlags()。
        this.setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
        mRenderer = new DemoRenderer();
        this.setRenderer(mRenderer);
    }

    public boolean onTouchEvent(final MotionEvent event) {
        //由于DemoRenderer对象运行在另一个线程中,这里采用跨线程的机制进行处理。使用queueEvent方法
        //当然也可以使用其他像Synchronized来进行UI线程和渲染线程进行通信。
        this.queueEvent(new Runnable() {

            @Override
            public void run() {
            }
        });

        return true;
    }

    class DemoRenderer implements GLSurfaceView.Renderer {

        @Override
        public void onDrawFrame(GL10 gl) {
            //每帧都需要调用该方法进行绘制。绘制时通常先调用glClear来清空framebuffer。
            //然后调用OpenGL ES其他接口进行绘制
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        }

        @Override
        public void onSurfaceChanged(GL10 gl, int w, int h) {
            //当surface的尺寸发生改变时,该方法被调用,。往往在这里设置ViewPort。或者Camara等。
            gl.glViewport(0, 0, w, h);
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // 该方法在渲染开始前调用,OpenGL ES的绘制上下文被重建时也会调用。
            //当Activity暂停时,绘制上下文会丢失,当Activity恢复时,绘制上下文会重建。
        }
    }
}

 

布局内配置

    <test.com.asproject.DemoGLSurfaceView
        android:id="@+id/gls_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </test.com.asproject.DemoGLSurfaceView>

 

共有 人打赏支持
粉丝 0
博文 13
码字总数 2786
×
march_kk
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: