GLSurfaceView布局内使用报空指针问题

来源:互联网 发布:棉花数据 编辑:程序博客网 时间:2024/05/01 09:54

看完了view,SurfaceView,GLSurfaceView的区别,想着每个用一下看看,结果在布局内写完加载就报错。

布局内配置

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

到此,GLSurfaceView已经可以使用了。

0 0
原创粉丝点击