0

My app crashes when I put layout.setVisibilty(VISIBLE) in my checkExit() method. my FATAL EXCEPTION crash log tells me its because of a null object reference. I can't see why, and I don't know how to fix it.

I've tried making layout static in my MainActivity, I've tried making it static in my GameView. I've tried changing where its initialised but I still can't see why it's being thrown.

My MainActivity code:

package com.example.practicingandroidwithsean.mazeone;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {


    boolean gameIsActive = true;

    public void playAgain(View view){

        View gameView = findViewById(R.id.gameView);
        LinearLayout layout = findViewById(R.id.playAgainLayout);
        Animation slideDown = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.slide_down);
        Animation slideUp = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.slide_up);

        if(gameView.getVisibility() == View.INVISIBLE){

            gameIsActive = false;
            layout.startAnimation(slideUp);
            layout.setVisibility(View.VISIBLE);


        }
    }

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

        LinearLayout layout = findViewById(R.id.playAgainLayout);
        layout.setVisibility(View.INVISIBLE);


    }
}

My GameView code... this is where everything mainly happens:

public class GameView extends View {

    public GameView(Context context) {
        super(context);
    }

    private enum Direction{ //data type of self defined constants
        UP, DOWN, LEFT, RIGHT
    }

    private static Cell[][] cells;
    public static Cell player, exit, trail;
    private static final int COLS = 12, ROWS = 18;
    private static final float WALL_THICKNESS = 4;
    private static ArrayList<Cell> trailList = new ArrayList<>();
    private float cellSize, hMargin, vMargin;
    private int counter = 0;
    private Paint wallPaint, playerPaint, exitPaint, trailPaint;
    private static Random random;
    private TextView TextViewTime;
    private int seconds, minutes;
    private boolean gameIsActive = true;

    LinearLayout layout;
    View gameView;


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

        wallPaint = new Paint();
        wallPaint.setColor(Color.WHITE);
        wallPaint.setStrokeWidth(WALL_THICKNESS);

        playerPaint = new Paint();
        playerPaint.setColor(Color.RED);

        exitPaint = new Paint();
        exitPaint.setColor(Color.BLUE);

        //   trailPaint = new Paint();
        //   trailPaint.setColor(Color.YELLOW);

        random = new Random();

        this.seconds = 0;
        this.minutes = 0;

        layout = findViewById(R.id.playAgainLayout);
        gameView = findViewById(R.id.gameView);

//        timer(findViewById(R.id.Timer));

        createMaze();
    }

public void createMaze(){

        Stack<Cell> stack = new Stack<>();
        Cell current, next;

        cells = new Cell[COLS][ROWS];

        for(int x=0; x<COLS; x++){
            for(int y=0; y<ROWS; y++){
                cells[x][y] = new Cell(x, y); //2 Dimensional array of cell objects for the whole msze
            }
        }

        player = cells[0][0]; //This is where the player starts
        exit = cells[COLS-1][ROWS-1]; //This is the exit


        current = cells[0][0];
        current.visited = true;

        do {
            next = getNeighbour(current);
            if (next != null) {
                removeWall(current, next);
                stack.push(current);
                current = next;
                current.visited = true;
            } else
                current = stack.pop(); //gives us the top element of the stack and removes it from the
        }while(!stack.empty());

        Animation slideUp = AnimationUtils.loadAnimation(getContext(), R.anim.slide_up);
        gameView.startAnimation(slideUp);

    }

public void checkExit() {
        if (player == exit && counter < 3) {
            counter++;

            Animation slideDown = AnimationUtils.loadAnimation(getContext(), R.anim.mazeslidedown);
            gameView.startAnimation(slideDown);
            gameView.setVisibility(INVISIBLE);

            layout.setVisibility(VISIBLE);

        }
    }

When the player == exit, the View slides away. This has no problems, but when I try to make the layout.setVisibility(Visible) to work when player==exit, the game crashes. Below is the error.

Process: com.example.practicingandroidwithsean.mazeone, PID: 4295
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.LinearLayout.setVisibility(int)' on a null object reference
        at com.example.practicingandroidwithsean.mazeone.GameView.checkExit(GameView.java:285)
        at com.example.practicingandroidwithsean.mazeone.GameView.movePlayer(GameView.java:273)
        at com.example.practicingandroidwithsean.mazeone.GameView.onTouchEvent(GameView.java:349)
        at android.view.View.dispatchTouchEvent(View.java:12540)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3159)
        at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2844)
        at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:601)
        at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1871)
        at android.app.Activity.dispatchTouchEvent(Activity.java:3384)
        at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
        at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:563)
        at android.view.View.dispatchPointerEvent(View.java:12788)
        at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5670)
        at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5465)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4958)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5011)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4977)
        at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5114)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4985)
        at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5171)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4958)
        at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5011)
        at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4977)
        at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4985)
        at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4958)
        at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7736)
        at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7676)
        at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7637)
        at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7847)
        at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:197)
        at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
        at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:186)
        at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:7810)
        at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:7874)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
        at android.view.Choreographer.doCallbacks(Choreographer.java:723)
        at android.view.Choreographer.doFrame(Choreographer.java:652)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
        at android.os.Handler.handleCallback(Handler.java:789)
E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6944)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Application terminated.

The expected results is for the View to slide away, as it does, and then for the playAgainLayout to slide up. This then allows for my playAgain button to work (I'll be creating this in the MainActivity.class). If it helps to know, the activity_main.xml contains a view which is linked to the gameView.

my activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black"
    tools:context=".MainActivity">

    <Chronometer
        android:id="@+id/chronometer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:textColor="@android:color/white"
        android:textSize="45sp"
        app:layout_constraintBottom_toTopOf="@+id/gameView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <view
        android:id="@+id/gameView"
        class="com.example.practicingandroidwithsean.mazeone.GameView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="140dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:background="@drawable/border"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <LinearLayout
        android:id="@+id/playAgainLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:background="@drawable/border"
        android:orientation="vertical"
        android:visibility="invisible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/wellDoneTV"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="Well Done!"
            android:textAlignment="center"
            android:textColor="@android:color/white"
            android:textSize="50sp" />

        <TextView
            android:id="@+id/gameTime"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:text="0:00"
            android:textAlignment="center"
            android:textColor="@android:color/white"
            android:textSize="30sp" />

        <Button
            android:id="@+id/playAgain"
            style="@style/Widget.AppCompat.Button.Colored"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/button_border"
            android:onClick="playAgain"
            android:text="Button"
            android:textColor="@android:color/white"
            android:textSize="25sp" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
Sean O
  • 238
  • 3
  • 14
  • check your id in .xml file – Sandeep Malik Jul 11 '19 at 12:12
  • all of the id's that are connected to their views are correct. I've double and triple checked this. – Sean O Jul 11 '19 at 12:21
  • `playAgainLayout` sits outside of `GameView`'s hierarchy - look at your xml layout file and you'll see. As a quick solution, lookup `playAgainLayout` within your Activity, and SET it on `GameView` – PPartisan Jul 11 '19 at 14:29

0 Answers0