2017-08-11 21 views
1

注:我知道這個問題是重複的,你很可能鼓勵downvote,但,如果檢查爲null,怎麼會有NullPointerException?

  • 這事發生在Android框架代碼
  • 它發生,即使有一個空檢查,沒有多線程。

我最近部署了我的APK在Play商店中,並收到NullPointerException了極少數用戶(4):

Exception java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Object.equals(java.lang.Object)' on a null object reference 
android.widget.AdapterView.getPositionForView (AdapterView.java:607) 
com.snap.testsnapboard.AlbumSelectActivity$1.onItemClick (AlbumSelectActivity.java:114) 
android.widget.AdapterView.performItemClick (AdapterView.java:305) 
android.widget.AbsListView.performItemClick (AbsListView.java:1146) 
android.widget.AbsListView$PerformClick.run (AbsListView.java:3057) 
android.widget.AbsListView.onTouchUp (AbsListView.java:3876) 
android.widget.AbsListView.onTouchEvent (AbsListView.java:3641) 
android.view.View.dispatchTouchEvent (View.java:8481) 
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2400) 
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2093) 
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2406) 
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2107) 
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2406) 
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2107) 
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2406) 
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2107) 
android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:2406) 
android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2107) 
com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent (PhoneWindow.java:2369) 
com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent (PhoneWindow.java:1719) 
android.app.Activity.dispatchTouchEvent (Activity.java:2785) 
com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent (PhoneWindow.java:2330) 
android.view.View.dispatchPointerEvent (View.java:8676) 
android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent (ViewRootImpl.java:4141) 
android.view.ViewRootImpl$ViewPostImeInputStage.onProcess (ViewRootImpl.java:4007) 
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3562) 
android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:3615) 
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3581) 
android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:3698) 
android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3589) 
android.view.ViewRootImpl$AsyncInputStage.apply (ViewRootImpl.java:3755) 
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3562) 
android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:3615) 
android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:3581) 
android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:3589) 
android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:3562) 
android.view.ViewRootImpl.deliverInputEvent (ViewRootImpl.java:5825) 
android.view.ViewRootImpl.doProcessInputEvents (ViewRootImpl.java:5799) 
android.view.ViewRootImpl.enqueueInputEvent (ViewRootImpl.java:5770) 
android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent (ViewRootImpl.java:5915) 
android.view.InputEventReceiver.dispatchInputEvent (InputEventReceiver.java:185) 
android.os.MessageQueue.nativePollOnce (MessageQueue.java) 
android.os.MessageQueue.next (MessageQueue.java:143) 
android.os.Looper.loop (Looper.java:122) 
android.app.ActivityThread.main (ActivityThread.java:5254) 
java.lang.reflect.Method.invoke (Method.java) 
java.lang.reflect.Method.invoke (Method.java:372) 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:902) 
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:697) 

這個例外在該行while ((v = (View) listItem.getParent()) != null && !v.equals(this)) {

起源於AdapterView.java

/** 
    * Returns the position within the adapter's data set for the view, where 
    * view is a an adapter item or a descendant of an adapter item. 
    * <p> 
    * <strong>Note:</strong> The result of this method only reflects the 
    * position of the data bound to <var>view</var> during the most recent 
    * layout pass. If the adapter's data set has changed without a subsequent 
    * layout pass, the position returned by this method may not match the 
    * current position of the data within the adapter. 
    * 
    * @param view an adapter item, or a descendant of an adapter item. This 
    *    must be visible in this AdapterView at the time of the call. 
    * @return the position within the adapter's data set of the view, or 
    *   {@link #INVALID_POSITION} if the view does not correspond to a 
    *   list item (or it is not currently visible) 
    */ 
    public int getPositionForView(View view) { 
     View listItem = view; 
     try { 
      View v; 
      while ((v = (View) listItem.getParent()) != null && !v.equals(this)) { 
       listItem = v; 
      } 
     } catch (ClassCastException e) { 
      // We made it up to the window without find this list view 
      return INVALID_POSITION; 
     } 

     if (listItem != null) { 
      // Search the children for the list item 
      final int childCount = getChildCount(); 
      for (int i = 0; i < childCount; i++) { 
       if (getChildAt(i).equals(listItem)) { 
        return mFirstPosition + i; 
       } 
      } 
     } 

     // Child not found! 
     return INVALID_POSITION; 
    } 

分其他的事情值得一提:

  • 我有一個連有一個頁腳視圖通過addFooterView()
  • 我要檢查,如果這頁腳視圖被點擊,什麼也不做,因爲這種觀點只是包含了一些列表視圖圖形不是通常的列表項目。
  • 對於這一點,我寫了下面的代碼:

      // Since we have a Footer view attached to the ListView, the position selected 
          // might not always map 1-to-1 with the ArrayList we are using to represent the 
          // Album model objects list. Lets check if the Footer view has been selected and 
          // in this case, do nothing. 
    
          if(myListView.getPositionForView(loadMoreView) == arg2){ 
           // Blank return 
           return; 
          } 
    

這是最終調用AdapterView.java裏面的方法的代碼。現在,爲什麼在while循環中有空檢查並且所有UI處理僅在主線程中發生時會有NullPointerException

+0

這是一個被重複關閉的高風險 - 空指針異常很快就會關閉 - 您可能想要添加這個問題中不同的問題,這些問題無法在upvoted Qs中得到解答,在這裏討論相同的問題 –

+0

@YvetteColomb:NullPointerException通用性足以被重複關閉。我希望在框架代碼中放棄一些光線,因爲畢竟有空檢查 –

+0

您如何確定異常的行? – Bob

回答

0

如果參數視圖爲空,那麼listItem也將爲空。這將導致NPE在這裏:

listItem.getParent() != null 
+1

但是,異常是在equals()方法中。這意味着&&的第一個子句成功執行。 –

1

我想告訴你一些關於空指針異常的提示。如果listItem爲空,它將創建異常...如果listItem不爲null,但listItem.getParent()爲null,它也會創建異常......或者當您將任何對象轉換爲另一個時, null..it拋出異常。

(v = (View) listItem.getParent()) != null && !v.equals(this) 

在你的情況,listItem.getParent()爲null這就是爲什麼它拋出異常。

,你應該這樣做:

if(v != null && listItem != null && listItem.getParent() != null && (v = (View) listItem.getParent()) != null && !v.equals(this) { 

} 

我希望它不會拋出異常。

+0

但條件說,v!= null。如果它真的那麼它會自動破解! –

+0

是的..它會破壞..但如果你膨脹視圖在v ..然後它不會中斷 – Naimatullah

相關問題