Android 成员访问上的SurfaceView NullPointerException

Android 成员访问上的SurfaceView NullPointerException,android,nullpointerexception,surfaceview,Android,Nullpointerexception,Surfaceview,我正在尝试创建一个程序,该程序接受太阳和行星的某些参数,并在扩展的SurfaceView类曲面中渲染可居住区域。我可以让它运行,只要我不尝试从主活动类访问曲面的任何成员,但曲面不显示。当我试图访问一个成员时,程序崩溃,我得到一个NullPointerException 以下是HabitalActivity.java(主要活动)的相关部分: 和Surface.java: public class Surface extends SurfaceView implements Runnable, On

我正在尝试创建一个程序,该程序接受太阳和行星的某些参数,并在扩展的SurfaceView类曲面中渲染可居住区域。我可以让它运行,只要我不尝试从主活动类访问曲面的任何成员,但曲面不显示。当我试图访问一个成员时,程序崩溃,我得到一个NullPointerException

以下是HabitalActivity.java(主要活动)的相关部分:

和Surface.java:

public class Surface extends SurfaceView implements Runnable, OnTouchListener {
    float x, y;
    double scale;
    Bitmap planet, sun;
    Paint paint = new Paint();
    SurfaceHolder holder;
    Thread thread = null;
    boolean isRunning = false;

    // TODO: delete these temp vars
    double liveMin = 1.0;
    double liveMax = 5.0;

    public Surface(Context context, AttributeSet attrs) {
        super(context, attrs);

        holder = getHolder();
        x = (float) 0.0;
        y = (float) 0.0;
        scale = 1.0;
        planet = BitmapFactory
                .decodeResource(getResources(), R.drawable.planet);
        sun = BitmapFactory.decodeResource(getResources(), R.drawable.sun);
    }

    // Functions
    protected void setScale(int canvasWidth) {
        // set liveMin and liveMax equal dist from edges
        scale = (canvasWidth + sun.getWidth() / 2.0) / (liveMin + liveMax);
    }

    public void resetSurface() {
        /*
         * TODO: set up process for resetting the surface (recalc habitable
         * zone, etc.)
         */
    }

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        x = event.getX();
        y = event.getY();

        return true; // Allows dragging
    }

    public void pause() {
        isRunning = false;
        while (true) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            break;
        }
        thread = null;
    }

    public void resume() {
        isRunning = true;
        thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {

        while (isRunning) {
            if (!holder.getSurface().isValid())
                continue;
            Canvas canvas = holder.lockCanvas();

            // Calculate
            setScale(canvas.getWidth());

            // Draw
            canvas.drawRGB(0, 0, 255);
            paint.setColor(Color.rgb(50, 200, 0));
            canvas.drawCircle(0, canvas.getHeight() / 2,
                    (float) (liveMax * scale), paint);
            paint.setColor(Color.rgb(255, 50, 0));
            canvas.drawCircle(0, canvas.getHeight() / 2,
                    (float) (liveMin * scale), paint);
            // TODO: draw text for liveMin and liveMax
            canvas.drawBitmap(sun, -sun.getWidth() / 2, canvas.getHeight() / 2
                    - sun.getHeight() / 2, null);
            canvas.drawBitmap(planet, x - planet.getWidth() / 2,
                    y - planet.getHeight() / 2, null);
            // TODO: draw text for T and r

            // Display
            holder.unlockCanvasAndPost(canvas);
        }
    }

}
如果有帮助,以下是布局XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".HabitableActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Phase" />

        <Spinner
            android:id="@+id/spinner1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Albedo:" />

        <SeekBar
            android:id="@+id/seekBar2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="tau" />

        <SeekBar
            android:id="@+id/seekBar1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

    </LinearLayout>

    <com.example.habitable.Surface
        android:id="@+id/surface"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

我认为你应该移动
setContentView(R.layout.activity\u habitable)super.onCreate(savedInstanceState)后立即调用code>因为现在这行:

surface = (Surface) findViewById(R.id.surface);

导致该曲面为空。它找不到R.id.surface,因为您尚未设置内容视图,并且布局未膨胀。

我认为您应该移动
设置内容视图(R.layout.activity\u habitable)super.onCreate(savedInstanceState)后立即调用code>因为现在这行:

surface = (Surface) findViewById(R.id.surface);

导致该曲面为空。它找不到R.id.surface,因为您还没有设置内容视图,而且布局也没有膨胀。

@Ruckus,您犯了一个愚蠢的错误,请参阅Michal的Answer@Ruckus,你犯了一个愚蠢的错误,请看迈克尔的回答谢谢。我一直在做这样的事情。通常我会抓到它。它没有显示或者你的线程没有启动?你在什么地方调用start()了吗?是的,在resume()方法中,它是从resume()的主要活动中调用的。我想出来了。我将线性布局在曲面上方的高度设置为匹配父对象而不是包裹内容。谢谢。我一直在做这样的事情。通常我会抓到它。它没有显示或者你的线程没有启动?你在什么地方调用start()了吗?是的,在resume()方法中,它是从resume()的主要活动中调用的。我想出来了。我将LinearLayout在曲面上方的高度设置为匹配父对象而不是包裹内容。
surface = (Surface) findViewById(R.id.surface);