调用onPause时,openGL场景中的对象在android线程中变为null

时间:2014-01-18 04:50:07

标签: java android multithreading opengl-es onpause

所以这是我的第一次线程,我正在使用连续更新场景。我一直在研究这个问题,到处寻找解释,这是我最后的理由。在我的GLWorld extends GLSurfaceView课程中,我创建了一个处理程序:

private static int threadID = 0;
private final WorldRenderer mRenderer;
private boolean running;
private Context context;
Handler timeHandler;
private int[] values;

public GLWorld(Context context, int values[])
{
    super(context);
    this.context = context;
    timeHandler = new Handler();

    // Create an OpenGL ES 2.0 context.
    setEGLContextClientVersion(2);

    // Set the Renderer for drawing on the GLSurfaceView
    Log.d("Test", "GL initialized");
    mRenderer = new WorldRenderer(context, values);
    setRenderer(mRenderer);
    this.startThread();
    timeHandler.postDelayed(tickThread, values[2] * 1000);

    // Render the view only when there is a change in the drawing data
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}

它运行的线程就是这个:

private Runnable tickThread = new Runnable() 
{
    public void run() 
    {
        threadID++;
        Log.d("tick", "start " + threadID + " "  + SystemClock.currentThreadTimeMillis());

        ArrayList<Point> points = new ArrayList<Point>(); 

        //work down and populate points not shown

        for(int i = 0; i < values[0]; i++)
        {

            for(int j = 0; j < values[1]; j++)
            {
                updateFire(i,j,points);
                points.clear();
            }
        }
        requestRender();
        Log.d("tick", "finish " + threadID + " " + SystemClock.currentThreadTimeMillis());
        Log.d("","");
        if(running)
            timeHandler.postDelayed(this, values[2]* 1000);

    }
};

现在,GLWorld对象存在于名为SimulationActivity的活动中。我将onPause / onResume定义为:

@Override
protected void onPause()
{
    super.onPause();
    // The following call pauses the rendering thread.
    // If your OpenGL application is memory intensive,
    // you should consider de-allocating objects that
    // consume significant memory here.
    mGLView.endThread();
    mGLView.onPause();
    Log.d("pause","pause called");
}

@Override
protected void onResume()
{
    super.onResume();
    // The following call resumes a paused rendering thread.
    // If you de-allocated graphic objects for onPause()
    // this is a good place to re-allocate them.
    mGLView.onResume();
    mGLView.startThread();
    Log.d("resume","resume called");
}

其中endthread / startthread分别发送运行为false / true。我的问题是,当我说,点击屏幕侧面的锁定按钮锁定屏幕,它做了一些我不明白的原因,我一直试图弄明白,以及尝试使用对象由线程中的OS设置为null。我看到它做什么(就在我锁定屏幕时,我甚至还没有恢复它)我的日志就是它

1)调用onPause,正确处理内部的内容

2)重新创建SimulationActivityonCreate因某种原因被召唤!

3)在GLWorld

中重新创建SimulationActivity对象

4)调用onResume(我不知道为什么会这样做,不应该根据我的理解)

5)再次呼叫onPause

6)现在tickThread的一个线程开始运行,我不知道为什么,因为它应该在至少第二个running

中将onPause设置为false的情况下停止

7)当我尝试访问名为mGrid的渲染器内的对象时,此线程运行第一个循环正常,然后第二次运行在我的updateFire函数中抛出空指针异常。请注意,this.mRenderer变量本身不会变为空。它内部的mGrid对象变为空

private void updateFire(int i, int j, ArrayList<Point> surroundingPoints)
{
    //check if renderer or the object is null
    if(this.mRenderer == null)
        Log.d("grid","null");
    else
        Log.d("grid","stuff");
    GridSquare currGrid = this.mRenderer.mGrid[i*values[1] + j];
    //do non question importance stuff
}  

老实说,我甚至不知道我是否正在穿线。

1 个答案:

答案 0 :(得分:0)

这是一个愚蠢的简单修复,我花了很多时间试图找到“正确”的方法来做到这一点。

private Runnable tickThread = new Runnable() 
{
    public void run() 
    {
        if(!running)
            return;

这就是我所做的。我不知道这是否正确,但在尝试了几十种不同的“解决方案”之后,这是我唯一想到的。

如果有其他人遇到此问题,我会尝试更多问题。

因此,在onCreate之后调用onResume的主要原因是应用程序活动生命周期android activity life cycle似乎onResume总是在onCreate之后调用。至于在onPause之后发生的onCreate,只有当应用程序在前台运行时才按下锁定键。我将测试here找到的答案来解决这个问题。如果该链接按照我希望的方式工作,那么这个问题将得到解决。