2011-05-25 76 views
8

我想創建我的第一個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"); 
     } 
    } 
} 

UPDATE:這是我的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> 
+1

嘿,你能告訴我你是怎麼解決的這個錯誤確切地說,因爲我得到了同樣的錯誤,並且當我在logcat中提到的行註釋時,它指向了不同的行。它有點奇怪? – 2012-12-04 09:04:41

回答

16

你如果透過堆棧跟蹤,你會看到一個 「造成的......」 行(有時不止一個)。最後一個是重要的一個。它說在NMG.java的第32行有一個空指針異常。那行,和前行,分別是:

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

顯然,id爲R.id.nmg沒有視圖是在佈局R.layout.nmg_layout。那是什麼導致你的問題。

+0

這很奇怪,因爲它確實存在於佈局文件和R.我添加到我原來的問題。 – 2011-05-25 03:13:52

+0

嗯。也許我算錯了?如果沒有,我建議在這兩行之間添加'assert nMGView!= null;'這行。看看是否會導致你的應用程序崩潰,而不是由NPE導致失敗。 – 2011-05-25 03:23:24

+0

嘗試過,但仍然因爲與之前相同的原因而失敗。 – 2011-05-25 03:33:19

1

在您的XML文件中,確實存在R.id.nmg。 所以我認爲問題是由資源的NMGView對象膨脹引起的。 您應該檢查您的NMGView源代碼,特別是在其構造函數中。

+0

我不確定膨脹是什麼意思。你能解釋一下你的意思嗎? – 2011-05-25 03:34:05

+0

我不認爲這是正確的。如果問題是由nmg_layout膨脹時實例化NMGView引起的,則會通過調用'setContentView'來產生異常。例外情況稍後。 – 2011-05-25 03:39:48

0

這個問題的發生是因爲當你銷燬surfaceView時大部分時間SurfaceView的onDraw()方法正在運行,那麼你會得到一個NULL POINTER ERROR,因爲那時畫布不存在。我已經解決了這個問題,抓住所有的繪圖東西與NullPointerException異常:

@Override 
public void onDraw(Canvas canvas) { 

    try { 
     //Drawing Stuff 

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

如果要實現在onPause()的onDestroy()在您的主要活動方式,你會得到以下順序:第一:E /的onPause:ON PAUSE - >下一步E/surfaceDestroyed:表面被毀 - > E /空指針異常:帆布空指針 - >最後 E /的onDestroy:將其銷燬

這是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"); 
     } 

} 
相關問題