Попытка вызвать виртуальный метод для нулевой ссылки на объект при получении значений из другого класса - PullRequest
0 голосов
/ 19 января 2019

У меня есть «игра» с двумя классами, один из которых содержит макеты и представления и управляет ими, а другой должен выполнять все необходимые вычисления. Не очень далеко, потому что когда я щелкаю TextView вместо отображения значения, приложение падает, выдавая следующую ошибку:

Попытка вызвать виртуальный метод void android.widget.TextView.setText (java.lang.CharSequence) 'с нулевым значением ссылка на объект

Обычно, когда я нажимаю на поле, оно должно перейти к методу во втором упражнении, увеличить индекс, а затем отобразить значение в нажатом TextView.

Это моя основная деятельность:

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 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: ИСКЛЮЧИТЕЛЬНОЕ ИСКЛЮЧЕНИЕ: основное Процесс: com.andygix.a40love, PID: 6684 java.lang.NullPointerException: попытка вызвать виртуальный метод «void android.widget.TextView.setText (java.lang.CharSequence)» на ссылка на нулевой объект на com.andygix.a40love.MainGame.writeGameScoreP1 (MainGame.java:116) на com.andygix.a40love.ScoreSetter.clickedByP1 (ScoreSetter.java:33) at com.andygix.a40love.MainGame $ 1.onClick (MainGame.java:59) на android.view.View.performClick (View.java:6294) на android.view.View $ PerformClick.run (View.java:24770) на android.os.Handler.handleCallback (Handler.java:790) на android.os.Handler.dispatchMessage (Handler.java:99) на android.os.Looper.loop (Looper.java:164) на android.app.ActivityThread.main (ActivityThread.java:6494) в java.lang.reflect.Method.invoke (родной метод) в com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run (RuntimeInit.java:438) на com.android.internal.os.ZygoteInit.main (ZygoteInit.java:807) 2019-01-18 23: 56: 23.002 1693-1953 / system_process W / ActivityManager:
Принудительное завершение деятельности com.andygix.a40love / .MainGame 2019-01-18 23: 56: 23.528 1693-1712 / system_process W / ActivityManager: Activity время ожидания для ActivityRecord {ea4853d u0 com.andygix.a40love / .MainGame t48 f} 2019-01-18 23: 56: 34.370 1693-1712 / system_process W / ActivityManager: Тайм-аут уничтожения активности для ActivityRecord {ea4853d u0 com.andygix.a40love / .MainGame t48 f}

В котором упоминается, что проблемы вызваны следующими методами:

gameScoreP1.setText(String.valueOf(valP1));

mainGame.writeGameScoreP1(indexP1);

scoreSetter.clickedByP1();

Я много искал и пробовал кучу разных методов, но ничего не помогло. Все идентификаторы в XML-файлах правильны и проверены трижды. Опять же, я хочу упомянуть то, что мне кажется странным: тот факт, что я записываю значение до того, как оно должно быть записано, корректно, но не воспринято TextView.

Ответы [ 2 ]

0 голосов
/ 19 января 2019

Вы не можете напрямую создавать экземпляры Activity или напрямую ссылаться на методы Activity, если ваш ссылочный класс не был создан целевым Activity.

В вашем случае вы не можете сделать это:

private MainGame mainGame = new MainGame();

Однако вы создаете экземпляр ScoreSetter из своей деятельности в MainGame, что означает, что у вас есть нужная ссылка. Вместо использования Context в конструкторе ScoreSetter используйте MainGame:

private MainGame mainGame; //don't instantiate it here

public ScoreSetter(MainGame mainGame) {
        this.mainGame = mainGame; //do it here instead
}

Теперь вы можете ссылаться на фактический экземпляр вашей Деятельности.

Если вы когда-либо сталкивались с ситуацией, когда ваш класс не содержится в Деятельности, которую необходимо обновить, вам следует изучить трансляции .

0 голосов
/ 19 января 2019

Проверка на ноль

if (gameScoreP1 != null) {
    gameScoreP1.setText(String.valueOf(valP1));
} else {
    Logger.d(TAG, "gameScoreP1 is null");
}
...