从另一个 class 获取值时尝试在空对象引用上调用虚拟方法
Attempt to invoke virtual method on a null object reference when taking values from another class
我有一个带有两个 class 的 "game",一个保存和管理布局和视图,另一个应该执行所有需要的计算。没有走得太远,因为当我单击 TextView 而不是显示值时,应用程序崩溃并提供以下错误:
Attempt to invoke virtual method 'void
android.widget.TextView.setText(java.lang.CharSequence)' on a null
object reference
通常,当我单击一个字段时,它应该转到第二个方法 activity,增加一个索引,然后在单击的 TextView 中显示该值。
这是我的主activity:
public class MainGame extends AppCompatActivity {
ConstraintLayout layout;
ConstraintSet mainLayout = new ConstraintSet();
ConstraintSet optionalLayout = new ConstraintSet();
ConstraintSet armbandLayout = new ConstraintSet();
ConstraintSet armbandOptionalLayout = new ConstraintSet();
private boolean isArmband = false;
private boolean isOptional = false;
TextView player1Name;
TextView fullNameP2;
TextView shortNameP1;
TextView shortNameP2;
TextView gameScoreP1;
TextView gameScoreP2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_game);
initializeLayoutViews();
initializeLayoutValues();
final ScoreSetter scoreSetter = new ScoreSetter(this);
scoreSetter.initIndex();
//scoreSetter.initAfterGameWon();
gameScoreP1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
scoreSetter.clickedByP1();
}
});
}
private void initializeLayoutViews() {
layout = findViewById(R.id.gameLayout);
mainLayout.clone(layout);
optionalLayout.clone(this, R.layout.activity_main_game_optional);
armbandLayout.clone(this, R.layout.activity_main_armband);
armbandOptionalLayout.clone(this, R.layout.activity_main_armband_optional);
player1Name = findViewById(R.id.fullNameP1);
fullNameP2 = findViewById(R.id.fullNameP2);
shortNameP1 = findViewById(R.id.shortNameP1);
shortNameP2 = findViewById(R.id.shortNameP2);
gameScoreP1 = findViewById(R.id.gameScoreP1);
gameScoreP2 = findViewById(R.id.gameScoreP2);
}
private void initializeLayoutValues() {
player1Name.setText("Player 1");
fullNameP2.setText("Player 2");
shortNameP1.setText("P1");
shortNameP2.setText("P2");
gameScoreP1.setText("0");
gameScoreP2.setText("0");
}
void writeGameScoreP1(int valP1) {
Log.i("MainGame_value", String.valueOf(valP1));
gameScoreP1.setText(String.valueOf(valP1));
}
}
奇怪的是日志显示了正确的值,只是没有显示在屏幕上;相反,它会使应用程序崩溃。
这是我的第二个 class:
class ScoreSetter {
private int[] GAME_SCORE_VALUES = new int[] {0, 15, 30, 40};
private int indexP1 = 0;
private int indexP2 = 0;
private int gameScoreP1;
private int gameScoreP2;
public String gameValueP1;
private String gameValueP2;
private MainGame mainGame = new MainGame();
ScoreSetter(Context context){
}
public void initIndex() {
indexP2 = 0;
indexP1 = 0;
}
public void initAfterGameWon() {
}
public void clickedByP1() {
++indexP1;
mainGame.writeGameScoreP1(indexP1);
}
}
这是日志:
2019-01-18 23:56:22.989 6684-6684/com.andygix.a40love
I/MainGame_value: 1 2019-01-18 23:56:22.991
6684-6684/com.andygix.a40love E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.andygix.a40love, PID: 6684
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a
null object reference
at com.andygix.a40love.MainGame.writeGameScoreP1(MainGame.java:116)
at com.andygix.a40love.ScoreSetter.clickedByP1(ScoreSetter.java:33)
at com.andygix.a40love.MainGame.onClick(MainGame.java:59)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
2019-01-18 23:56:23.002 1693-1953/system_process W/ActivityManager:
Force finishing activity com.andygix.a40love/.MainGame 2019-01-18
23:56:23.528 1693-1712/system_process W/ActivityManager: Activity
pause timeout for ActivityRecord{ea4853d u0
com.andygix.a40love/.MainGame t48 f} 2019-01-18 23:56:34.370
1693-1712/system_process W/ActivityManager: Activity destroy timeout
for ActivityRecord{ea4853d u0 com.andygix.a40love/.MainGame t48 f}
其中提到问题是由以下方法引起的:
gameScoreP1.setText(String.valueOf(valP1));
mainGame.writeGameScoreP1(indexP1);
scoreSetter.clickedByP1();
我到处搜索并尝试了很多不同的方法,但似乎没有任何效果。 xml 文件中的所有 ID 均正确并经过三重检查。我想再次提及对我来说似乎很奇怪的事情:我在应该写入值之前记录值,它是正确的但没有被 TextView 接受。
检查空值
if (gameScoreP1 != null) {
gameScoreP1.setText(String.valueOf(valP1));
} else {
Logger.d(TAG, "gameScoreP1 is null");
}
您不能直接实例化 Activity 或直接引用 Activity 方法,除非您的引用 class 是由目标 Activity 实例化的。
在你的情况下,你不能这样做:
private MainGame mainGame = new MainGame();
但是,您是从 MainGame Activity 实例化 ScoreSetter,这意味着您拥有所需的参考。不要在 ScoreSetter 的构造函数中使用 Context
,而是使用 MainGame
:
private MainGame mainGame; //don't instantiate it here
public ScoreSetter(MainGame mainGame) {
this.mainGame = mainGame; //do it here instead
}
现在您可以引用 Activity.
的实际实例
如果您 运行 遇到 class 不包含在需要更新的 Activity 中的情况,你应该看看 broadcasts.
我有一个带有两个 class 的 "game",一个保存和管理布局和视图,另一个应该执行所有需要的计算。没有走得太远,因为当我单击 TextView 而不是显示值时,应用程序崩溃并提供以下错误:
Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
通常,当我单击一个字段时,它应该转到第二个方法 activity,增加一个索引,然后在单击的 TextView 中显示该值。
这是我的主activity:
public class MainGame extends AppCompatActivity {
ConstraintLayout layout;
ConstraintSet mainLayout = new ConstraintSet();
ConstraintSet optionalLayout = new ConstraintSet();
ConstraintSet armbandLayout = new ConstraintSet();
ConstraintSet armbandOptionalLayout = new ConstraintSet();
private boolean isArmband = false;
private boolean isOptional = false;
TextView player1Name;
TextView fullNameP2;
TextView shortNameP1;
TextView shortNameP2;
TextView gameScoreP1;
TextView gameScoreP2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_game);
initializeLayoutViews();
initializeLayoutValues();
final ScoreSetter scoreSetter = new ScoreSetter(this);
scoreSetter.initIndex();
//scoreSetter.initAfterGameWon();
gameScoreP1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
scoreSetter.clickedByP1();
}
});
}
private void initializeLayoutViews() {
layout = findViewById(R.id.gameLayout);
mainLayout.clone(layout);
optionalLayout.clone(this, R.layout.activity_main_game_optional);
armbandLayout.clone(this, R.layout.activity_main_armband);
armbandOptionalLayout.clone(this, R.layout.activity_main_armband_optional);
player1Name = findViewById(R.id.fullNameP1);
fullNameP2 = findViewById(R.id.fullNameP2);
shortNameP1 = findViewById(R.id.shortNameP1);
shortNameP2 = findViewById(R.id.shortNameP2);
gameScoreP1 = findViewById(R.id.gameScoreP1);
gameScoreP2 = findViewById(R.id.gameScoreP2);
}
private void initializeLayoutValues() {
player1Name.setText("Player 1");
fullNameP2.setText("Player 2");
shortNameP1.setText("P1");
shortNameP2.setText("P2");
gameScoreP1.setText("0");
gameScoreP2.setText("0");
}
void writeGameScoreP1(int valP1) {
Log.i("MainGame_value", String.valueOf(valP1));
gameScoreP1.setText(String.valueOf(valP1));
}
}
奇怪的是日志显示了正确的值,只是没有显示在屏幕上;相反,它会使应用程序崩溃。
这是我的第二个 class:
class ScoreSetter {
private int[] GAME_SCORE_VALUES = new int[] {0, 15, 30, 40};
private int indexP1 = 0;
private int indexP2 = 0;
private int gameScoreP1;
private int gameScoreP2;
public String gameValueP1;
private String gameValueP2;
private MainGame mainGame = new MainGame();
ScoreSetter(Context context){
}
public void initIndex() {
indexP2 = 0;
indexP1 = 0;
}
public void initAfterGameWon() {
}
public void clickedByP1() {
++indexP1;
mainGame.writeGameScoreP1(indexP1);
}
}
这是日志:
2019-01-18 23:56:22.989 6684-6684/com.andygix.a40love I/MainGame_value: 1 2019-01-18 23:56:22.991 6684-6684/com.andygix.a40love E/AndroidRuntime: FATAL EXCEPTION: main Process: com.andygix.a40love, PID: 6684 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference at com.andygix.a40love.MainGame.writeGameScoreP1(MainGame.java:116) at com.andygix.a40love.ScoreSetter.clickedByP1(ScoreSetter.java:33) at com.andygix.a40love.MainGame.onClick(MainGame.java:59) at android.view.View.performClick(View.java:6294) at android.view.View$PerformClick.run(View.java:24770) at android.os.Handler.handleCallback(Handler.java:790) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6494) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 2019-01-18 23:56:23.002 1693-1953/system_process W/ActivityManager:
Force finishing activity com.andygix.a40love/.MainGame 2019-01-18 23:56:23.528 1693-1712/system_process W/ActivityManager: Activity pause timeout for ActivityRecord{ea4853d u0 com.andygix.a40love/.MainGame t48 f} 2019-01-18 23:56:34.370 1693-1712/system_process W/ActivityManager: Activity destroy timeout for ActivityRecord{ea4853d u0 com.andygix.a40love/.MainGame t48 f}
其中提到问题是由以下方法引起的:
gameScoreP1.setText(String.valueOf(valP1));
mainGame.writeGameScoreP1(indexP1);
scoreSetter.clickedByP1();
我到处搜索并尝试了很多不同的方法,但似乎没有任何效果。 xml 文件中的所有 ID 均正确并经过三重检查。我想再次提及对我来说似乎很奇怪的事情:我在应该写入值之前记录值,它是正确的但没有被 TextView 接受。
检查空值
if (gameScoreP1 != null) {
gameScoreP1.setText(String.valueOf(valP1));
} else {
Logger.d(TAG, "gameScoreP1 is null");
}
您不能直接实例化 Activity 或直接引用 Activity 方法,除非您的引用 class 是由目标 Activity 实例化的。
在你的情况下,你不能这样做:
private MainGame mainGame = new MainGame();
但是,您是从 MainGame Activity 实例化 ScoreSetter,这意味着您拥有所需的参考。不要在 ScoreSetter 的构造函数中使用 Context
,而是使用 MainGame
:
private MainGame mainGame; //don't instantiate it here
public ScoreSetter(MainGame mainGame) {
this.mainGame = mainGame; //do it here instead
}
现在您可以引用 Activity.
的实际实例如果您 运行 遇到 class 不包含在需要更新的 Activity 中的情况,你应该看看 broadcasts.