尝试在 Android 片段中查找按钮 ID 时抛出 NPE
NPE thrown when trying to Find Button ID in Android Fragment
无论我重做多少次,这个问题都反复出现。根据 Android 开发人员的说法,片段的视图层次结构中对象的 ID 是在 onCreateView 期间获得的,我在这里仔细研究的所有问题都证实了这一点。但是由于某种原因,在我进行设置的检查过程中它总是 returns null,因此我无法继续使用这些按钮。片段在该项目的 "decision events" 期间加载,每个事件都有不同的决定。因此,我只想使用一个片段并根据需要更改按钮文本。但是我似乎无法让他们不 return null。我只需要帮助找出导致 NPE 的我做错了什么。
DecisionFragment.java:
package com.saphiric.simproject.uimanipulation;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.saphiric.simproject.R;
import com.saphiric.simproject.datacontrols.DataCore;
public class DecisionFragment extends Fragment {
// Activity/Global variables
private static final String TAG = "DecisionFragment";
DataCore dataCore = DataCore.getInstance();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "Begin: Inflate");
// Gets handles to important UI elements for scalability
View root = inflater.inflate(R.layout.fragment_decision, container, false);
Button buttonTrue = (Button) root.findViewById(R.id.btnChoiceOne);
Button buttonFalse = (Button) root.findViewById(R.id.btnChoiceTwo);
if(buttonTrue == null){
System.out.println("buttonTrue is null");
} else {
System.out.println("buttonTrue is working fine");
}
Log.i(TAG, "Finished: Inflate");
if (root == null){
Log.e(TAG, "omg Inflate == null");
}
switch (dataCore.controller.getCurrentDecision()){
case "OPSDecision":
// buttonTrue.setText(R.string.ops_decision_one);
// buttonFalse.setText(R.string.ops_decision_two);
break;
default:
System.out.println("ERROR: No decision set");
}
return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
}
fragment_decision.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="90dp"
android:orientation="horizontal"
android:weightSum="1.0"
tools:context="com.saphiric.simproject.uimanipulation.DecisionFragment">
<Button
android:id="@+id/decisionOne"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_weight=".5"
android:text="@string/defaul_btn"
android:onClick="cryingDecisionOne"/>
<Button
android:id="@+id/decisionTwo"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_weight=".5"
android:text="@string/defaul_btn"
android:onClick="cryingDecisionTwo"/>
</LinearLayout>
DayOne.java:
package com.saphiric.simproject.activities;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.saphiric.simproject.R;
import com.saphiric.simproject.datacontrols.DataCore;
import com.saphiric.simproject.uimanipulation.ControlsFragment;
import com.saphiric.simproject.uimanipulation.DecisionFragment;
/**
* Created by Saphiric on 11/12/14.
*/
public class DayOne extends Activity {
/**
* Necessary activity variables
*/
ControlsFragment controlsFragment = new ControlsFragment();
DecisionFragment decisionFragment = new DecisionFragment();
DataCore dataCore = DataCore.getInstance();
/**
* Android activity methods
*
* @param savedInstanceState is the apps savedInstanceState
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_day_one);
// Initializes the opening story text
// Initializes the dayProgress variable in DataController
String storyStart = getResources().getString(R.string.story_opening_one);
dataCore.controller.setCurrentText(storyStart);
dataCore.controller.setCurrentDecision("OPSDecision");
// Handles for fragment management
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// UI will add the ControlsFragment in it's starting state for that activity.
fragmentTransaction.add(R.id.fragmentContainer, controlsFragment);
fragmentTransaction.commit();
}
@Override
public void onResume(){
super.onResume();
}
public void cryingDecisionOne(View view) {
dataCore.controller.setDayProgress(dataCore.controller.getDayProgress());
// Sets cryingDecision Story Lock
dataCore.locks.setCryingDecision(true);
dataCore.controller.setCurrentDecision("HLSOne");
// Removes the decision fragment and replaces it with the controls fragment
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Sets the text to be pulled to storyText
String decision = getResources().getString(R.string.crying_decision_true);
dataCore.controller.setCurrentText(decision);
fragmentTransaction.replace(R.id.fragmentContainer, controlsFragment);
fragmentTransaction.commit();
}
public void cryingDecisionTwo(View view) {
dataCore.controller.setDayProgress(dataCore.controller.getDayProgress());
// Sets cryingDecision choice
dataCore.locks.setCryingDecision(false);
dataCore.controller.setCurrentDecision("HWSOne");
// Removes the decision fragment and replaces it with the controls fragment
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Updates the currentText for updating the story view
String decision = getResources().getString(R.string.crying_decision_false);
dataCore.controller.setCurrentText(decision);
fragmentTransaction.replace(R.id.fragmentContainer, controlsFragment);
fragmentTransaction.commit();
}
public void advanceGameFunction(View view) {
String textUpdate;
// Handles for fragment management
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Obtains handles to UI components
TextView storyText = (TextView) findViewById(R.id.storyText);
RelativeLayout gameStart = (RelativeLayout) findViewById(R.id.gameStart);
ImageView charOne = (ImageView) findViewById(R.id.char_one);
ImageView charTwo = (ImageView) findViewById(R.id.char_two);
ImageView charThree = (ImageView) findViewById(R.id.char_three);
ImageView charFour = (ImageView) findViewById(R.id.char_four);
// Increments the data variable in DataController
dataCore.controller.setDayProgress(dataCore.controller.getDayProgress());
System.out.println(dataCore.controller.getDayProgress());
// Switch case for handling day progression
switch (dataCore.controller.getDayProgress()) {
case 1:
textUpdate = getResources().getString(R.string.story_opening_two);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
break;
case 2:
fragmentTransaction.replace(R.id.fragmentContainer, decisionFragment);
fragmentTransaction.commit();
break;
case 3:
if (dataCore.locks.getCryingDecision()) {
storyText.setText(dataCore.controller.getCurrentText());
} else {
storyText.setText(dataCore.controller.getCurrentText());
}
break;
case 4:
if (dataCore.locks.getCryingDecision()) {
textUpdate = getResources().getString(R.string.ops_d1_line1);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
} else {
textUpdate = getResources().getString(R.string.ops_d2_line1);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}
break;
case 5: // Transition to hurt leg scene if Crying Decision is true, hallway scene if false
if (dataCore.locks.getCryingDecision()){
gameStart.setBackgroundResource(R.drawable.bg_gym_front);
textUpdate = getResources().getString(R.string.hls_line1);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}else{
gameStart.setBackgroundResource(R.drawable.bg_hallway);
textUpdate = getResources().getString(R.string.hws_line1);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}
break;
case 6:
if(dataCore.locks.getCryingDecision()){
textUpdate = getResources().getString(R.string.hls_line2);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}else{
textUpdate = getResources().getString(R.string.hws_line2);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}
break;
case 7:
if(dataCore.locks.getCryingDecision()){
charOne.setVisibility(View.VISIBLE);
textUpdate = getResources().getString(R.string.hls_line3);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}else {
}
break;
case 8:
if(dataCore.locks.getCryingDecision()){
textUpdate = getResources().getString(R.string.hls_line4);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}else{
}
break;
case 9:
if(dataCore.locks.getCryingDecision()){
}else{
}
break;
default:
System.out.println("Default case called");
}
}
}
您在代码中使用了错误的 ID!您布局中的按钮具有 ID decisionOne
和 decisionTwo
但在您的代码中您使用的是 btnChoiceOne
和 btnChoiceTwo
.
要修复它,请替换为:
Button buttonTrue = (Button) root.findViewById(R.id.btnChoiceOne);
Button buttonFalse = (Button) root.findViewById(R.id.btnChoiceTwo);
在你的 DecisionFragment
:
Button buttonTrue = (Button) root.findViewById(R.id.decisionOne);
Button buttonFalse = (Button) root.findViewById(R.id.decisionTwo);
代码中的按钮 ID 与 xml 布局中的不匹配。
在你的 xml 中,id 是 'decisionOne' 但代码正在寻找 'R.id.btnChoiceOne'
无论我重做多少次,这个问题都反复出现。根据 Android 开发人员的说法,片段的视图层次结构中对象的 ID 是在 onCreateView 期间获得的,我在这里仔细研究的所有问题都证实了这一点。但是由于某种原因,在我进行设置的检查过程中它总是 returns null,因此我无法继续使用这些按钮。片段在该项目的 "decision events" 期间加载,每个事件都有不同的决定。因此,我只想使用一个片段并根据需要更改按钮文本。但是我似乎无法让他们不 return null。我只需要帮助找出导致 NPE 的我做错了什么。
DecisionFragment.java:
package com.saphiric.simproject.uimanipulation;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.saphiric.simproject.R;
import com.saphiric.simproject.datacontrols.DataCore;
public class DecisionFragment extends Fragment {
// Activity/Global variables
private static final String TAG = "DecisionFragment";
DataCore dataCore = DataCore.getInstance();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "Begin: Inflate");
// Gets handles to important UI elements for scalability
View root = inflater.inflate(R.layout.fragment_decision, container, false);
Button buttonTrue = (Button) root.findViewById(R.id.btnChoiceOne);
Button buttonFalse = (Button) root.findViewById(R.id.btnChoiceTwo);
if(buttonTrue == null){
System.out.println("buttonTrue is null");
} else {
System.out.println("buttonTrue is working fine");
}
Log.i(TAG, "Finished: Inflate");
if (root == null){
Log.e(TAG, "omg Inflate == null");
}
switch (dataCore.controller.getCurrentDecision()){
case "OPSDecision":
// buttonTrue.setText(R.string.ops_decision_one);
// buttonFalse.setText(R.string.ops_decision_two);
break;
default:
System.out.println("ERROR: No decision set");
}
return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
}
fragment_decision.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="90dp"
android:orientation="horizontal"
android:weightSum="1.0"
tools:context="com.saphiric.simproject.uimanipulation.DecisionFragment">
<Button
android:id="@+id/decisionOne"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_weight=".5"
android:text="@string/defaul_btn"
android:onClick="cryingDecisionOne"/>
<Button
android:id="@+id/decisionTwo"
android:layout_width="0dp"
android:layout_height="90dp"
android:layout_weight=".5"
android:text="@string/defaul_btn"
android:onClick="cryingDecisionTwo"/>
</LinearLayout>
DayOne.java:
package com.saphiric.simproject.activities;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.saphiric.simproject.R;
import com.saphiric.simproject.datacontrols.DataCore;
import com.saphiric.simproject.uimanipulation.ControlsFragment;
import com.saphiric.simproject.uimanipulation.DecisionFragment;
/**
* Created by Saphiric on 11/12/14.
*/
public class DayOne extends Activity {
/**
* Necessary activity variables
*/
ControlsFragment controlsFragment = new ControlsFragment();
DecisionFragment decisionFragment = new DecisionFragment();
DataCore dataCore = DataCore.getInstance();
/**
* Android activity methods
*
* @param savedInstanceState is the apps savedInstanceState
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_day_one);
// Initializes the opening story text
// Initializes the dayProgress variable in DataController
String storyStart = getResources().getString(R.string.story_opening_one);
dataCore.controller.setCurrentText(storyStart);
dataCore.controller.setCurrentDecision("OPSDecision");
// Handles for fragment management
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// UI will add the ControlsFragment in it's starting state for that activity.
fragmentTransaction.add(R.id.fragmentContainer, controlsFragment);
fragmentTransaction.commit();
}
@Override
public void onResume(){
super.onResume();
}
public void cryingDecisionOne(View view) {
dataCore.controller.setDayProgress(dataCore.controller.getDayProgress());
// Sets cryingDecision Story Lock
dataCore.locks.setCryingDecision(true);
dataCore.controller.setCurrentDecision("HLSOne");
// Removes the decision fragment and replaces it with the controls fragment
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Sets the text to be pulled to storyText
String decision = getResources().getString(R.string.crying_decision_true);
dataCore.controller.setCurrentText(decision);
fragmentTransaction.replace(R.id.fragmentContainer, controlsFragment);
fragmentTransaction.commit();
}
public void cryingDecisionTwo(View view) {
dataCore.controller.setDayProgress(dataCore.controller.getDayProgress());
// Sets cryingDecision choice
dataCore.locks.setCryingDecision(false);
dataCore.controller.setCurrentDecision("HWSOne");
// Removes the decision fragment and replaces it with the controls fragment
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Updates the currentText for updating the story view
String decision = getResources().getString(R.string.crying_decision_false);
dataCore.controller.setCurrentText(decision);
fragmentTransaction.replace(R.id.fragmentContainer, controlsFragment);
fragmentTransaction.commit();
}
public void advanceGameFunction(View view) {
String textUpdate;
// Handles for fragment management
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Obtains handles to UI components
TextView storyText = (TextView) findViewById(R.id.storyText);
RelativeLayout gameStart = (RelativeLayout) findViewById(R.id.gameStart);
ImageView charOne = (ImageView) findViewById(R.id.char_one);
ImageView charTwo = (ImageView) findViewById(R.id.char_two);
ImageView charThree = (ImageView) findViewById(R.id.char_three);
ImageView charFour = (ImageView) findViewById(R.id.char_four);
// Increments the data variable in DataController
dataCore.controller.setDayProgress(dataCore.controller.getDayProgress());
System.out.println(dataCore.controller.getDayProgress());
// Switch case for handling day progression
switch (dataCore.controller.getDayProgress()) {
case 1:
textUpdate = getResources().getString(R.string.story_opening_two);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
break;
case 2:
fragmentTransaction.replace(R.id.fragmentContainer, decisionFragment);
fragmentTransaction.commit();
break;
case 3:
if (dataCore.locks.getCryingDecision()) {
storyText.setText(dataCore.controller.getCurrentText());
} else {
storyText.setText(dataCore.controller.getCurrentText());
}
break;
case 4:
if (dataCore.locks.getCryingDecision()) {
textUpdate = getResources().getString(R.string.ops_d1_line1);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
} else {
textUpdate = getResources().getString(R.string.ops_d2_line1);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}
break;
case 5: // Transition to hurt leg scene if Crying Decision is true, hallway scene if false
if (dataCore.locks.getCryingDecision()){
gameStart.setBackgroundResource(R.drawable.bg_gym_front);
textUpdate = getResources().getString(R.string.hls_line1);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}else{
gameStart.setBackgroundResource(R.drawable.bg_hallway);
textUpdate = getResources().getString(R.string.hws_line1);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}
break;
case 6:
if(dataCore.locks.getCryingDecision()){
textUpdate = getResources().getString(R.string.hls_line2);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}else{
textUpdate = getResources().getString(R.string.hws_line2);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}
break;
case 7:
if(dataCore.locks.getCryingDecision()){
charOne.setVisibility(View.VISIBLE);
textUpdate = getResources().getString(R.string.hls_line3);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}else {
}
break;
case 8:
if(dataCore.locks.getCryingDecision()){
textUpdate = getResources().getString(R.string.hls_line4);
dataCore.controller.setCurrentText(textUpdate);
storyText.setText(dataCore.controller.getCurrentText());
}else{
}
break;
case 9:
if(dataCore.locks.getCryingDecision()){
}else{
}
break;
default:
System.out.println("Default case called");
}
}
}
您在代码中使用了错误的 ID!您布局中的按钮具有 ID decisionOne
和 decisionTwo
但在您的代码中您使用的是 btnChoiceOne
和 btnChoiceTwo
.
要修复它,请替换为:
Button buttonTrue = (Button) root.findViewById(R.id.btnChoiceOne);
Button buttonFalse = (Button) root.findViewById(R.id.btnChoiceTwo);
在你的 DecisionFragment
:
Button buttonTrue = (Button) root.findViewById(R.id.decisionOne);
Button buttonFalse = (Button) root.findViewById(R.id.decisionTwo);
代码中的按钮 ID 与 xml 布局中的不匹配。
在你的 xml 中,id 是 'decisionOne' 但代码正在寻找 'R.id.btnChoiceOne'