2015-05-31 55 views
0

我對我的Android代碼中的一個非常小的問題感到困惑。這些靜態getter&setter方法有什麼問題 - Android?

05-31 13:37:13.222 29262-29262/com.whitsoft.stan E/AndroidRuntime﹕ FATAL EXCEPTION: main 
java.lang.NullPointerException 
     at com.whitsoft.stan.mods.ResultsRoomInfoCustRLYT.setSingleRoomsNumberTextValue(ResultsRoomInfoCustRLYT.java:61) 
     at com.whitsoft.stan.utils.DataFixer.updateRelevantViewsWithSelectedData(DataFixer.java:48) 
     at com.whitsoft.stan.mods.StanListFragment.checkIfTheListAdapterDataHasChanged(StanListFragment.java:98) 
     at com.whitsoft.stan.mods.StanListFragment.onActivityCreated(StanListFragment.java:49) 
     at android.app.Fragment.performActivityCreated(Fragment.java:1707) 
     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:921) 
     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1075) 
     at android.app.BackStackRecord.run(BackStackRecord.java:682) 
     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1455) 
     at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441) 
     at android.os.Handler.handleCallback(Handler.java:730) 
     at android.os.Handler.dispatchMessage(Handler.java:92) 
     at android.os.Looper.loop(Looper.java:137) 
     at android.app.ActivityThread.main(ActivityThread.java:5493) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:525) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025) 
     at dalvik.system.NativeStart.main(Native Method) 

這裏就是干將& setter方法來實現自定義類(「ResultsRoomInfoCustRLYT」):所有的getter和setter我在一個自定義類(即「ResultsRoomInfoCustRLYT」)給我下面的Java NullPointerException異常「創建:

public class ResultsRoomInfoCustRLYT extends RelativeLayout { 

LayoutInflater stanInflater; 
private static TextView singleRoomsNumberTV, singleRoomsDescTV, vipRoomsNumberTV, vipRoomsDescTV; 

public ResultsRoomInfoCustRLYT(Context context) { 
    super(context); 

    stanInflater = LayoutInflater.from(context); 
    initializeAndLayoutChildren(); 
} 

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

    stanInflater = LayoutInflater.from(context); 
    initializeAndLayoutChildren(); 
} 

public ResultsRoomInfoCustRLYT(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 

    stanInflater = LayoutInflater.from(context); 
    initializeAndLayoutChildren(); 
} 

private void initializeAndLayoutChildren() { 

    stanInflater.inflate(R.layout.cust_rlyt_results_room_info, this, true); 

    singleRoomsNumberTV = (TextView) findViewById(R.id.stan_Single_Rooms_Number_TV); 
    singleRoomsDescTV = (TextView) findViewById(R.id.stan_Single_Rooms_Description_TV); 
    vipRoomsNumberTV = (TextView) findViewById(R.id.stan_VIP_Rooms_Number_TV); 
    vipRoomsDescTV = (TextView) findViewById(R.id.stan_VIP_Rooms_Description_TV); 
} 

public static String getSingleRoomsNumberTextValue() { 
    return singleRoomsNumberTV.getText().toString(); 
} 

public static void setSingleRoomsNumberTextValue(String singleRoomsNumberText) { 
    singleRoomsNumberTV.setText(singleRoomsNumberText); 
} 

public static void setVipRoomsNumberTextValue (String vipRoomsNumberText) { 
    vipRoomsNumberTV.setText(vipRoomsNumberText); 
} 

public static String getVipRoomsDescTextValue() { 
    return vipRoomsDescTV.getText().toString(); 
} 

public static void setVipRoomsDescTextValue (String vipRoomsDescText) { 
    vipRoomsDescTV.setText(vipRoomsDescText); 
} } 

...你可以看到我喜歡使用靜態getter和setter方法,因爲它給了我方便地訪問到所需的意見與一個單一的代碼行。我在運行時遇到的這個錯誤真的很奇怪,就是我有另外兩個類,像這個使用完全相同的設置類 - 而且這些類可以正常工作(根據需要更新數據)。然而,當這個類的安裝者被以下調用呼叫時,他們都不能執行:

ResultsRoomInfoCustRLYT.setSingleRoomsNumberTextValue(singleRoomsNumberInfo); 
    ResultsRoomInfoCustRLYT.setSingleRoomsDescTextValue(singleRoomsDescInfo); 
    ResultsRoomInfoCustRLYT.setVipRoomsNumberTextValue(vipRoomsNumberInfo); 
    ResultsRoomInfoCustRLYT.setVipRoomsDescTextValue(vipRoomsDescInfo); 

任何幫助將不勝感激。謝謝。 Shore-T。

+0

你在調用setter之前運行了initializeAndLayoutChildren()函數嗎? –

+1

你確定你的'findViewById'調用返回正確的視圖引用,而不是'null'(如果找不到傳入的* id,就會發生這種情況)。並使其快速:對於實例變量的靜態getter和setter是非常糟糕的代碼。 – Tom

+0

哇,謝謝湯姆 - 你把這個問題釘在頭上。實際上,我爲這個自定義類創建了兩個佈局.xml文件(一個用於縱向視圖,另一個用於佈局視圖)。在我的匆忙中,我沒有檢查TextView ID在縱向和橫向佈局文件中是否相同。因此,'findViewById()'方法實際上只在運行時將縱向佈局文件視圖(TextViews)鏈接到Java,而不是橫向視圖,因爲它們具有不同的ID。這是什麼導致設備處於橫向方向時的錯誤。我的愚蠢的錯誤 - 我喜歡拍自己! –

回答

2

那麼問題是,你正試圖設置一些null文本視圖的文本。例如,下面一行:

ResultsRoomInfoCustRLYT.setSingleRoomsNumberTextValue(singleRoomsNumberInfo); 

試圖做到以下幾點:

singleRoomsNumberTV.setText(singleRoomsNumberText); 

但什麼是singleRoomsNumberTV?它在哪裏分配?您需要致電:

new ResultsRoomInfoCustRLYT(this); 

從您的活動中初始化靜態TextViews。

+0

Matei,你和湯姆都是對的。然而,你是唯一一個提供了答案的人,我可以在這裏選擇正確的答案......所以你得到了「綠色標記」。感謝所有盡力幫助我的人 - 尤其包括Eran。 –

1

您的靜態getter和setter將訪問通過非靜態方法初始化的靜態引用 - initializeAndLayoutChildren。當你在一個非靜態方法中初始化一個靜態變量時,你會冒着在初始化之前訪問靜態變量的風險。您還要冒多次初始化靜態變量的風險 - 每次創建新實例時。

例如,靜態方法setSingleRoomsNumberTextValue訪問靜態變量singleRoomsNumberTV它獲取通過的ResultsRoomInfoCustRLYT構造稱爲實例方法initializeAndLayoutChildren初始化。如果您在創建任何ResultsRoomInfoCustRLYT實例之前調用該靜態方法,您將獲得NullPointerException

+0

這聽起來很符合邏輯Eran,但在這種情況下,每次調用類構造函數時都會調用'initializeAndLayoutChildren'非靜態方法(每當您對類名稱進行引用時都會調用這個方法 - 就像運行此代碼時一樣: 'ResultRoomInfoCustRLYT.setSingleRoomsNumberTextValue(singleRoomsNumberInfo);'...所以在調用靜態getter和setter方法之前實際上沒有不初始化相關視圖的風險,因此這不是在這種情況下的正確答案 - 請參閱初始發佈的評論。'謝謝你的努力' –

+0

*「每當你對類名引用時都會發生 - 就像你運行這段代碼時一樣:'ResultsRoomInfoCustRLYT.setSingleRoomsNumberTextValue(singleRoomsNumberInfo);'...所以實際上沒有在調用靜態getter和setter方法之前沒有初始化相關視圖的風險「*所以你認爲,如果你調用靜態方法li你提到的那個構造函數會被調用嗎?這是錯誤的。既然這是錯誤的,你的假設,即沒有風險,也是錯誤的。 – Tom

+0

@ Shore-T不,引用類名不會調用該類的構造函數,創建該類的實例(這正是您接受的答案告訴您要做的)。我沒有提出這樣的建議,因爲從非靜態方法初始化靜態變量似乎是個不好的設計。 – Eran