Android开发:“线程退出未捕获的异常”

时间:2011-05-25 02:57:50

标签: java android

我正在尝试创建我的第一个Android应用程序(游戏),但我在开始时遇到了一些困难。

当我运行我的代码时,我收到此错误日志:

05-25 02:41:51.022: WARN/dalvikvm(634): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): FATAL EXCEPTION: main
05-25 02:41:51.040: ERROR/AndroidRuntime(634): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.stickfigs.nmg/com.stickfigs.nmg.NMG}: java.lang.NullPointerException
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.app.ActivityThread.access$2300(ActivityThread.java:125)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.os.Looper.loop(Looper.java:123)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.app.ActivityThread.main(ActivityThread.java:4627)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at java.lang.reflect.Method.invokeNative(Native Method)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at java.lang.reflect.Method.invoke(Method.java:521)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at dalvik.system.NativeStart.main(Native Method)
05-25 02:41:51.040: ERROR/AndroidRuntime(634): Caused by: java.lang.NullPointerException
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at com.stickfigs.nmg.NMG.onCreate(NMG.java:32)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
05-25 02:41:51.040: ERROR/AndroidRuntime(634):     ... 11 more
05-25 02:41:51.062: WARN/ActivityManager(59):   Force finishing activity com.stickfigs.nmg/.NMG

我认为问题是这个“线程退出未捕获的异常”部分,我不知道异常是什么或导致它的原因。

这是我的代码:

NMGView.java:     包com.stickfigs.NMG;

import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

class NMGView extends SurfaceView implements SurfaceHolder.Callback {

    class NMGThread extends Thread {
        //State-tracking constants
        public static final int STATE_LOSE = 1;
        public static final int STATE_PAUSE = 2;
        public static final int STATE_READY = 3;
        public static final int STATE_RUNNING = 4;
        public static final int STATE_WIN = 5;

        /** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */
        private int mode;

        /** Handle to the surface manager object we interact with */
        private SurfaceHolder surfaceHolder;

        public NMGThread(SurfaceHolder surfaceHolderc, Context contextc) {
            // get handles to some important objects
            surfaceHolder = surfaceHolderc;
            context = contextc;

        }

        /**
         * Restores game state from the indicated Bundle. Typically called when
         * the Activity is being restored after having been previously
         * destroyed.
         * 
         * @param savedState Bundle containing the game state
         */
        public synchronized void restoreState(Bundle savedState) {
            synchronized (surfaceHolder) {
                setState(STATE_PAUSE);
                }
        }

        /**
         * Sets the game mode. That is, whether we are running, paused, in the
         * failure state, in the victory state, etc.
         * 
         * @param mode one of the STATE_* constants
         * @param message string to add to screen or null
         */
        public void setState(int modec) {
            synchronized (surfaceHolder) {
                mode = modec;
            }
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }

    /** Handle to the application context, used to e.g. fetch Drawables. */
    private Context context;

    /** The thread that actually draws the animation */
    private NMGThread thread;

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

        // register our interest in hearing about changes to our surface
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);

        // create thread only; it's started in surfaceCreated()
        thread = new NMGThread(holder, context);

        setFocusable(true); // make sure we get key events
    }

    /**
     * Fetches the animation thread corresponding to this LunarView.
     * 
     * @return the animation thread
     */
    public NMGThread getThread() {
        return thread;
    }
}

NMG.java:

package com.stickfigs.nmg;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;

import com.stickfigs.nmg.NMGView.NMGThread;

public class NMG extends Activity {
    /** Called when the activity is first created. */

    /** A handle to the thread that's actually running the animation. */
    private NMGThread nMGThread;

    /** A handle to the View in which the game is running. */
    private NMGView nMGView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Turn off the window's title bar
        // TODO Turn off the status bar
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        // tell system to use the layout defined in our XML file
        setContentView(R.layout.nmg_layout);

        // get handles to the LunarView from XML, and its LunarThread
        nMGView = (NMGView) findViewById(R.id.nmg);
        nMGThread = nMGView.getThread();

        if (savedInstanceState == null) {
            // we were just launched: set up a new game
            nMGThread.setState(NMGThread.STATE_READY);
            Log.w(this.getClass().getName(), "SIS is null");
        } else {
            // we are being restored: resume a previous game
            nMGThread.restoreState(savedInstanceState);
            Log.w(this.getClass().getName(), "SIS is nonnull");
        }
    }
}

更新:这是我的R.java和nmg_layout.xml:

R.java:     包com.stickfigs.nmg;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int nmg=0x7f050000;
    }
    public static final class layout {
        public static final int nmg_layout=0x7f030000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}

nmg_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.stickfigs.nmg.NMGView
      android:id="@+id/nmg"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"/>
</FrameLayout>

4 个答案:

答案 0 :(得分:16)

如果查看堆栈跟踪,您将看到“由......引起”行(有时不止一行)。最后一个是重要的一个。它说NMG.java的第32行有一个空指针异常。该行以及之前的行是:

nMGView = (NMGView) findViewById(R.id.nmg);
nMGThread = nMGView.getThread();

显然,状态R.id.nmg中没有ID为R.layout.nmg_layout的视图。这就是造成你问题的原因。

答案 1 :(得分:1)

在您的XML文件中,R.id.nmg确实存在。 所以我认为问题是由资源中的NMGView对象膨胀引起的。 您应该检查NMGView源代码,尤其是在其构造函数中。

答案 2 :(得分:1)

如果您在“ build.gradle(Module:app)”中使用“ multiDexEnabled true ”,请从“ defaultConfig ”中删除此行>”并同步项目。
就我而言,它可以工作!!!!

答案 3 :(得分:0)

出现这个问题是因为大多数时候SurfaceView onDraw()方法在你破坏surfaceView时运行,然后你得到一个NULL POINTER ERROR,因为那一刻画布不存在。我已经修复了使用NullPointerException捕获所有绘图内容的问题:

@Override
public void onDraw(Canvas canvas) {

    try {
         //Drawing Stuff

   }catch(NullPointerException e){
        Log.e("NULL POINTER EXCEPTION","Canvas NULL POINTER");
    }
}

如果在Main活动中实现onPause(),onDestroy()方法,您将获得以下顺序:first:E / onPause:ON PAUSE - &gt; next E / surfaceDestroyed:SURFACE DESTROYED - &gt; E / NULL指针异常:Canvas NULL POINTER - &gt;最后 E / onDestroy:DESTROY

这是我正在使用的surfaceDestroyed方法:

   @Override
public void surfaceDestroyed(SurfaceHolder arg0) {
    Log.e("surfaceDestroyed", "SURFACE DESTROYED ");


    thread.setRunning(false);
        try {
            //thread.setRunning(false);
            thread.join();
            } catch (InterruptedException e) {
           Log.e("Surface Thread Stopped","SURFACE THREAD STOPPED");
        }

}