fluffywarthog
fluffywarthog

Reputation: 61

FATAL exception: setOnClickListener on a null object in Android Studio

I'm writing a basic word scramble app in Android Studio, and have gotten everything laid out and the methods working, but I'm getting a fatal exception when I send it to my debugger.

Here's my java:

package com.example.admin.androidwordscramble;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.Random;
import java.util.Scanner;


public class WordScramble extends ActionBarActivity {
EditText playerEdit;
TextView textUpper;
TextView textInstruction;
Button buttonNew;
Button buttonPlay;
String playerInput;
char[] answerWord;
char[] playerWord;
char[] scrambledWord;
final String word1 = "APPLE";
final String word2 = "CLOVE";
final String word3 = "LEMON";
final String word4 = "ONION";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_word_scramble);
    initControls();    //Where my logcat says the first error is.
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_word_scramble, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

void initControls() {
    playerEdit = (EditText)findViewById(R.id.playerEdit);
    textUpper = (TextView)findViewById(R.id.textUpper);
    textInstruction = (TextView)findViewById((R.id.textInstruction));
    textUpper.setText("Scramble Game");

    buttonNew.setOnClickListener(new Button.OnClickListener()    //Where the logcat says the second error is.
    {
        public void onClick
                (View v) { newGame();}});
    buttonPlay.setOnClickListener(new Button.OnClickListener()
    {public void onClick
                (View v) { playGame();}});
}

void newGame() {
    playerEdit.setText("");
    answerWord = toArray(word1);
    shuffle(answerWord);
    textUpper.setText(scrambledWord.toString());
    textInstruction.setText("Unscramble it!");
}

void playGame() {
    playerInput = playerEdit.getText().toString();
    playerWord = toArray(playerInput);

    if(testWord()) {
        textUpper.setText(answerWord.toString());
        textInstruction.setText("Correct!");
    }
    else {
        textInstruction.setText("Incorrect. Try again!");
    }
}

char[] shuffle(char[] answerWord) {
    Random rand = new Random();
    char[] scrambledWord = new char[5];

    for (int i = 0; i < scrambledWord.length; i++)
        scrambledWord[i] = answerWord[i];

    final int max = 5;
    for (int i = 0; i < max; i++) {
        int k = rand.nextInt(scrambledWord.length);
        int j = rand.nextInt(scrambledWord.length);
        char temp = scrambledWord[k];
        scrambledWord[k] = scrambledWord[j];
        scrambledWord[j] = temp;
    }
    return scrambledWord;
}

boolean testWord() {
    final int max = 5;
    int i = 0;
    while (i < max) {
        if (playerWord[i] != answerWord[i])
            return false;
        else {
            i++;
        }
    }
    return true;
}

    char[] toArray(String wordString) {
    Scanner read = new Scanner(wordString);
    char[] wordArray = new char[5];

    for (int i = 0; i < 5; i++) {
        wordArray[i] = wordString.charAt(i);
    }
    return wordArray;
}
}

My XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".WordScramble">

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="NEW"
    android:id="@+id/buttonNew"
    android:layout_marginBottom="58dp"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_marginLeft="47dp"
    android:layout_marginStart="47dp" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="PLAY"
    android:id="@+id/buttonPlay"
    android:layout_alignTop="@+id/buttonNew"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_marginRight="47dp"
    android:layout_marginEnd="47dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Unscramble it!"
    android:id="@+id/textInstruction"
    android:layout_above="@+id/buttonNew"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="167dp" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/playerEdit"
    android:layout_above="@+id/buttonNew"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="75dp"
    android:inputType="text"
    android:hint="Try here"
    android:textIsSelectable="true"
    android:capitalize="characters" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="New Text"
    android:id="@+id/textUpper"
    android:layout_above="@+id/textInstruction"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="36dp" />

Log cat states:

E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.admin.androidwordscramble, PID: 2405
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.admin.androidwordscramble/com.example.admin.androidwordscramble.WordScramble}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
            ....
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
            at com.example.admin.androidwordscramble.WordScramble.initControls(WordScramble.java:67)
            at com.example.admin.androidwordscramble.WordScramble.onCreate(WordScramble.java:36)

I've cleaned and rebuilt a couple times, but it still crashes the emulator and spits out an exception in the debugger. Can anyone point out where I went wrong with the button pointing?

Edit: Logcat for when the app froze:

    07-29 14:39:00.168      627-653/? E/ActivityManager﹕ ANR in com.example.admin.project03 (com.example.admin.project03/.WordScramble)
    PID: 1782
    Reason: Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago.  Wait queue length: 2.  Wait queue head age: 13282.2ms.)
    Load: 0.95 / 0.57 / 0.23
    CPU usage from 7918ms to 0ms ago:
    99% 1782/com.example.admin.project03: 99% user + 0% kernel / faults: 3756 minor
    2.6% 627/system_server: 0.1% user + 2.5% kernel / faults: 77 minor
    1.2% 250/vinput: 0% user + 1.2% kernel
    0.1% 8/rcu_preempt: 0% user + 0.1% kernel
    0% 96/adbd: 0% user + 0% kernel / faults: 2 minor
    0% 245/healthd: 0% user + 0% kernel
    0.1% 254/local_gps: 0% user + 0.1% kernel
    0% 783/wpa_supplicant: 0% user + 0% kernel
    25% TOTAL: 24% user + 0.6% kernel + 0.3% softirq
    CPU usage from 2350ms to 2858ms later:
    101% 1782/com.example.admin.project03: 101% user + 0% kernel / faults: 200 minor
    98% 1782/admin.project03: 98% user + 0% kernel
    1.8% 1797/GCDaemon: 1.8% user + 0% kernel
    5.8% 627/system_server: 1.9% user + 3.9% kernel / faults: 3 minor
    1.9% 639/FinalizerDaemon: 0% user + 1.9% kernel
    1.9% 645/SensorService: 0% user + 1.9% kernel
    1.9% 653/ActivityManager: 1.9% user + 0% kernel
    26% TOTAL: 25% user + 1% kernel
07-29 14:39:00.338     627-1830/? D/OpenGLRenderer﹕ Render dirty regions requested: true
07-29 14:39:00.338      627-653/? D/Atlas﹕ Validating map...
07-29 14:39:00.437     627-1830/? I/OpenGLRenderer﹕ Initialized EGL, version 1.4
07-29 14:39:00.437     627-1830/? D/﹕ HostConnection::get() New Host Connection established 0xafc9b9a0, tid 1830
07-29 14:39:00.532      627-645/? D/Sensors﹕ Client connection accepted (186)
07-29 14:39:00.632     627-1830/? D/OpenGLRenderer﹕ Enabling debug mode 0
07-29 14:39:00.644     627-1830/? W/EGL_emulation﹕ eglSurfaceAttrib not implemented
07-29 14:39:00.644     627-1830/? W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xafca9480, error=EGL_SUCCESS

Edit2: Added a while statement to prevent a crash if playGame was called, but now getting a FATAL NullpointerException right at the while statement.

void playGame() {
    while (answerWord != null) {
        playerInput = playerEdit.getText().toString();
        playerWord = toArray(playerInput);

        if (testWord()) {
            textUpper.setText(answerWord.toString());
            textInstruction.setText("Correct!");
        } else {
            textInstruction.setText("Incorrect. Try again!");
        }
    }
}

Upvotes: 0

Views: 1173

Answers (1)

user007
user007

Reputation: 2172

Your buttonNew and buttonPlay are never initialized before calling the setOnClickListener, you need to add findViewById statements, to get a handle to the buttons in the view, giving them the same id in XML as the variable name does not give you the handle. So, before setting the OnClickListener you need to add ::

buttonNew = (Button) findViewById(R.id.buttonNew);
buttonPlay = (Button) findViewById(R.id.buttonPlay);

Just like you did for playerEdit, etc. All the variables are initialized null by default, so without finding the view, you are calling setOnClickListener on null object, and hence the exception.

Upvotes: 1

Related Questions