2017-02-24 59 views
1

有人會解釋爲什麼我要爲我的cardView獲得NPE嗎?對我來說完全是無稽之談。這裏是所有相關的代碼和堆棧跟蹤:爲什麼findViewById爲CardView返回null?

活動舉辦CardView

public class MainScreen extends AppCompatActivity implements TipView.OnValueChangedListener 
{ 

private TipView tipView; 

private CardView cardView; 

private TextView tipTextView; 
private TextView taxTextView; 
private TextView splitTextView; 
private TextView productTextView; 
private TextView totalTextView; 

private TextView youPayEachPay; 


private ImageButton productEditButton; 
private ImageButton dataToggle; 

private ProductTotalWindow productTotalWindow; 



private double productTotal = 0.0d; 

private double currentTip = 0.0d; 
private double currentTax = 0.0d; 
private int currentSplit = 1; 


private NumberFormat currencyFormat; 


private String pricesDefaults = "$0.00"; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main_screen); 


    cardView = (CardView) findViewById(R.id.tipViewCardLayoutContainer).findViewById(R.id.cardViewId); 

    //NPE is thrown since, obviously the reference points to a null object 
    cardView.setCardBackgroundColor(Color.RED); 


    this.tipView = (TipView) findViewById(R.id.tipView); 
     tipView.setOnValueChangedListener(this); 



    dataToggle = (ImageButton) findViewById(R.id.dataToggle); 
    dataToggle.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      expandLayout(); 
     } 
    }); 



    initDataPricesViews(); 

    initProductEditView(); 

    currencyFormat = NumberFormat.getCurrencyInstance(); 

    } 

} 

XML代碼的主要佈局

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/activity_main_screen" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.bryan.tipease.MainScreen"> 


    <!-- 
    tipview_card_container is the layout hosting my cardview 
    --> 
<include 
    layout="@layout/tipview_card_container" 
    android:id="@id/tipViewCardLayoutContainer" /> 




<FrameLayout 
    android:layout_alignParentBottom="true" 
    android:layout_below="@id/tipViewCardLayoutContainer" 
    android:id="@id/pricesTotalContainer" 

    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 


<include layout="@layout/prices_layout" /> 

</FrameLayout> 



</RelativeLayout> 



//The cards xml file itself 

<?xml version="1.0" encoding="utf-8"?> 
<android.support.v7.widget.CardView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 

    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 

    android:id="@id/cardViewId" 

    app:contentPadding="16dp" 
    app:cardElevation="16dp" 
    app:cardBackgroundColor="@color/tipViewCardBackground"> 


    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <com.example.bryan.tipease.TipView 
      style="@style/WidgetTipViewStyle" 

      android:id="@id/tipView" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" /> 



    <ImageButton 
     style="@style/BreakerBarContent" 
     android:src="@drawable/forkknifefab" 
     android:id="@id/productDialogLauncher" 
     android:contentDescription="@string/contentDescForkKnifeImage" 

     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 


    <ImageButton 
     style="@style/BreakerBarContent" 
     android:src="@drawable/toggle_circle" 
     android:id="@id/dataToggle" 
     android:contentDescription="@string/contentDescDataToggleImage" 

     android:layout_alignParentRight="true" 
     android:layout_alignParentEnd="true" 

     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 
</RelativeLayout> 

    </android.support.v7.widget.CardView> 

堆棧跟蹤

02-23 21:06:55.548 26169-26169/? E/AndroidRuntime: FATAL EXCEPTION: main 
               Process: com.example.bryan.tipease, PID: 26169 
               java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bryan.tipease/com.example.bryan.tipease.MainScreen}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.CardView.setCardBackgroundColor(int)' on a null object reference 
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2378) 
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2440) 
                at android.app.ActivityThread.access$800(ActivityThread.java:162) 
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1348) 
                at android.os.Handler.dispatchMessage(Handler.java:102) 
                at android.os.Looper.loop(Looper.java:135) 
                at android.app.ActivityThread.main(ActivityThread.java:5422) 
                at java.lang.reflect.Method.invoke(Native Method) 
                at java.lang.reflect.Method.invoke(Method.java:372) 
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914) 
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707) 
               Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.CardView.setCardBackgroundColor(int)' on a null object reference 
                at com.example.bryan.tipease.MainScreen.onCreate(MainScreen.java:62) 
                at android.app.Activity.performCreate(Activity.java:6056) 
                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106) 
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2331) 
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2440)  
                at android.app.ActivityThread.access$800(ActivityThread.java:162)  
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1348)  
                at android.os.Handler.dispatchMessage(Handler.java:102)  
                at android.os.Looper.loop(Looper.java:135)  
                at android.app.ActivityThread.main(ActivityThread.java:5422)  
                at java.lang.reflect.Method.invoke(Native Method)  
                at java.lang.reflect.Method.invoke(Method.java:372)  
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)  
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)  

這是一個奇怪的問題,我只能重新創建一次。我認爲問題在於我如何引用cardview,關於使用include標籤,但是創建測試應用程序以查看是否可以重新創建此問題,但是我的引用沒有問題。

P.S.爲了簡潔起見,我從活動中省略了一些方法,但請相信我,它們與我的問題的原因無關。 P.S.S. 我可以參考該層次結構中的任何其他視圖。

+1

首先,您不需要像那樣鏈接'findViewById()'調用。層次結構將從上到下進行搜索,因此只需查找您最終想要的內容即可。其次,''上的'id'覆蓋了包含的佈局中的'View'的'id',所以'CardView'以ID'tipViewCardLayoutContainer'結束。只需從''中刪除'id',並用'R.id.cardViewId'調用'findViewById()'。 –

+0

我不知道包含ID會覆蓋根視圖。非常感謝你爲我省下了5個頭撞牆的哈哈! – whompum

回答

3

As @Mike M.在上述評論中提到。

首先

像你這樣在這裏你不需要鏈您findViewById()的:

cardView = (CardView) findViewById(R.id.tipViewCardLayoutContainer).findViewById(R.id.cardViewId);

View層次結構將從上往下搜索。這意味着你應該搜索你想要的android:id="@+id,而不是鏈接它們。

idandroid:id="@id/tipViewCardLayoutContainer"<include>覆蓋根Viewid,這意味着你的CardView現在有tipViewCardLayoutContainerid而不是android:id="@id/cardViewId"

所有你需要做的是從你的<include>刪除id並調用

CardView cardview = (CardView) findViewById(R.id.cardViewId);

0

我覺得ID應該使用+ ID喜歡this.hope這可以幫助你。

<include 
layout="@layout/tipview_card_container" 
android:id="@+id/tipViewCardLayoutContainer" /> 
+0

「@ id/tipViewCardLayoutContainer」引用了已經生成的id資源,因此不需要「+」。邁克上面有正確的答案:) – whompum