-1

I am working on a project where I need 3 textViews to change when a button is clicked.

Here is my MainActivity class:

package davidferrara.insultgenerator;

import android.content.res.Resources;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import java.util.Random;

public class MainActivity extends AppCompatActivity {

    private boolean mHomeLayout = true;
    private Resources res;
    private TextView tvInsult1;
    private TextView tvInsult2;
    private TextView tvInsult3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(mHomeLayout) {
            setContentView(R.layout.home_screen);
        }
        else {
            setContentView(R.layout.insult_screen);
        }

        findViewById(R.id.generateInsultButton).setOnClickListener(btnMainButton);

        assignTextViews();

    }

    //The generate insult button
    final View.OnClickListener btnMainButton = new View.OnClickListener() {
        @Override
        public void onClick(final View v) {
            mHomeLayout = false;
            setContentView(R.layout.insult_screen);
            generateInsult();
        }
    };

    private void generateInsult(){
        res = getResources();

        String[] array1 = res.getStringArray(R.array.insults0);
        String randomStr1 = array1[new Random().nextInt(array1.length)];
        tvInsult1.setText(randomStr1);

        String[] array2 = res.getStringArray(R.array.insults1);
        String randomStr2 = array2[new Random().nextInt(array2.length)];
        tvInsult2.setText(randomStr2);

        String[] array3 = res.getStringArray(R.array.insults2);
        String randomStr3 = array3[new Random().nextInt(array3.length)];
        tvInsult3.setText(randomStr3);
    }

    private void assignTextViews(){
        tvInsult1 = findViewById(R.id.insultText1);
        tvInsult2 = findViewById(R.id.insultText2);
        tvInsult3 = findViewById(R.id.insultText3);
    }
}

In this class I have 3 textViews, tvInsult1, tvInsult2, and tvInsult3 that are declared. These are then assigned the corresponding textViews from the insult_screen using the assignTextViews method.

When the button is clicked, it sets the layout to insult_screen and the generateInsult method is called. In this method, I set the string variable randomStr1 a string from an array of strings stored in my values folder. The textView tvInsult1 then gets the text set using randomStr1, or so it should.

When I ran the program, I got this error for the line tvInsult1.setText(randomStr1);:

01-04 18:44:51.160 7699-7699/davidferrara.insultgenerator E/AndroidRuntime: FATAL EXCEPTION: main
                                                                        Process: davidferrara.insultgenerator, PID: 7699
                                                                        java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference

I went back and put a break right before that line of code to debug it and it turns out that tvInsult1 was null. This is where I'm stuck. I already assigned the views using the findViewById. I've looked at multiple other issues similar to this one but none of the solutions worked for me.

Here is the other related code:

Home Screen XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">

<TextView
    android:id="@+id/textView4"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/welcome_message" />

<Button
    android:id="@+id/generateInsultButton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/generate_button" />

</LinearLayout>

Insult Screen XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="vertical"
tools:context="davidferrara.insultgenerator.MainActivity">

<TextView
    android:id="@+id/insultText1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="visible" />

<TextView
    android:id="@+id/insultText2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="visible" />

<TextView
    android:id="@+id/insultText3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="visible" />

<Button
    android:id="@+id/generateInsultButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/generate_button" />

</LinearLayout>

Here is a picture of the debugger saying that the array isn't empty and that the randomStr1 has a value assigned to it from the array: Picture of the debugger.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
DaveMcFave
  • 232
  • 1
  • 4
  • 13
  • Are you sure `array1` is not empty? – statosdotcom Jan 05 '18 at 00:35
  • This question is too long.. You should show only the necessary part of your code. – Taslim Oseni Jan 05 '18 at 00:59
  • @statosdotcom The arrays are not empty. When I debugged I made sure that the randomstr1 was assigned a random string from the array and it was. – DaveMcFave Jan 05 '18 at 02:45
  • @Taslim When I was looking through other similar questions the comments were saying that not enough information was present. That's why I included the error message as well as my layout code. – DaveMcFave Jan 05 '18 at 02:47
  • @DaveMcFave , excuse me, how did you stored these values on values folder? `string from an array of strings stored in my values folder`? And, if you comment those three lines `String[] array1 = res.getStringArray(R.array.insults0); String randomStr1 = array1[new Random().nextInt(array1.length)]; tvInsult1.setText(randomStr1);` what happens? I think you will get error on the next attribution: `tvInsult2.setText(randomStr2);`, so the array is empty. – statosdotcom Jan 05 '18 at 02:55
  • @statosdotcom I made a resource file called `string-arrays.xml` located in the values folder. I updated the post with a picture of the debugger showing values stored in the array. As for commenting the 3 lines out, the same error happens, just on `tvInsult2.setText(randomStr2);` – DaveMcFave Jan 05 '18 at 15:37

1 Answers1

2

The problem is with the layout XMLs you are using. You are trying to use a textview named insultText1 with your home_screen layout XML loaded, and it doesn't have that TV, only insult_layout has it (you invoked home_screen by mHomeLayout = true).

statosdotcom
  • 3,109
  • 2
  • 17
  • 40
  • Do you know a possible work around? I want the contentView to be home_screen.xml until the button is pressed. Then I want it to be insult_screen.xml for the rest of the time. I looked into splash screens before, but I wanted to try this method first. – DaveMcFave Jan 05 '18 at 16:25
  • Yes, just open another activity using insult_screen.xml. Know how to do this? Easy, crate another class with it. I'm curious to see this bunch of insults running :D – statosdotcom Jan 05 '18 at 16:28
  • With faith and patience, divide in two java files what you have now only as one (main_activity). On the first you let only the basic things: the welcome message and the **insult me** button :). On the second activity (call it insult.java, for example) you use all the rest of your code (the two layout xml files you've already got). To open a new activity just seach, google or here, very easy. But, another subject, so, please, if my answer was correct, please check it. Thanks. – statosdotcom Jan 05 '18 at 16:33
  • This solution did work. My first intention was to have one java class that switches different layouts, but since this method does work, I will keep it. – DaveMcFave Jan 05 '18 at 19:17