Search code examples
javaandroid-studionullpointerexceptionruntimeexception

Exception when going to another activity


I keep getting a NullPointerException when going to my other activity and the app/emulator just crashes.

The manifest file has both activities.

Here is the MainActivity:

public class MainActivity extends AppCompatActivity {
//Garbage Sorting V1

// GUI variables
private Button whereIsItems;
private Button addItem;
private TextView items;
private TextView listThings;


// Model: Database of items
private static ItemsDB itemsDB;

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

    itemsDB = new ItemsDB();
    itemsDB.fillItemsDB();

    items = findViewById(R.id.items);
    items.setText("Where to place them:");

    listThings = findViewById(R.id.edit_text);

    whereIsItems = findViewById(R.id.where_button);
    whereIsItems.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            items.setBackgroundColor(Color.parseColor("#FFFFFF"));
            String str = listThings.getText().toString();
            listThings.setText(itemsDB.getItemValue(str));
        }
    });

    addItem = findViewById(R.id.add_button1);
    assert addItem != null;
    addItem.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, GarbageActivity.class);
            startActivity(intent);
        }
    });
}

The other activity GarbageActivity (the one i'm trying to go to):

public class GarbageActivity extends AppCompatActivity {
private static ItemsDB itemsDB;
private EditText whatText;
private EditText whereText;
private Button addItem;

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

    itemsDB = ItemsDB.get(GarbageActivity.this);

    addItem = findViewById(R.id.add_button2);
    addItem.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            whatText = findViewById(R.id.what_text);
            whereText = findViewById(R.id.where_text);

            String str1 = whatText.getText().toString();
            String str2 = whereText.getText().toString();

            itemsDB.addItem(str1, str2);
            whatText.setText("");
            whereText.setText("");
        }
    });
}

Here is ItemsDB since debugger says there is an error here:

public class ItemsDB {
private Map<String, Item> ItemsDB;
private static ItemsDB sItemsDB;

public ItemsDB() {
    ItemsDB = new HashMap<>();
}

private ItemsDB(Context context)  {
    fillItemsDB();
}

public static ItemsDB get(Context context) {
    if (sItemsDB == null) sItemsDB = new ItemsDB(context);
    return sItemsDB;
}

public void addItem(String what, String where) {
    Item it = new Item(what, where);
    ItemsDB.put(it.getWhat(), it);
}

public String getItemValue(String itemName) {
    Item item = ItemsDB.get(itemName);
    if (item == null) {
        return itemName + " not found";
    } else {
        return itemName + " should be placed in " + ItemsDB.get(itemName).getWhere();
    }
}

public void fillItemsDB() {
    addItem("Milk Carton", "Cardboard");
    addItem("Carrots", "Food");
    addItem("T-shirt", "Not found");
    addItem("Bread", "Food");
    addItem("Butter", "Food");
}

garbage.xml:

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

<!-- Textview for heading -->
<TextView
    android:id="@+id/items"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<!-- Text field to enter item -->
<EditText
    android:id="@+id/edit_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="text"
    android:layout_marginBottom="5dp"/>

<Button
    android:id="@+id/where_button"
    android:layout_width="wrap_content"
    android:layout_gravity="left"
    android:background="#39f208"
    android:text="Where"
    android:layout_height="80sp"/>

<Button
    android:id="@+id/add_button1"
    android:layout_width="wrap_content"
    android:layout_gravity="left"
    android:background="#39f208"
    android:text="Add an item"
    android:layout_height="80sp"/>
</LinearLayout>

garbage_activity.xml:

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

<TableLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:id="@+id/textView5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="What Item?"
            android:textAppearance="@style/TextAppearance.AppCompat.Large" />

        <EditText
            android:id="@+id/what_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:id="@+id/textView6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Where?"
            android:textAppearance="@style/TextAppearance.AppCompat.Large" />

        <EditText
            android:id="@+id/where_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <Button
            android:id="@+id/add_button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Add an Item" />
    </TableRow>
</TableLayout>
</LinearLayout>

This is my first question on here, so bear with me ;)

EDIT Here is the debugger log:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: dk.itu.sortinggarbageapp, PID: 8926
java.lang.RuntimeException: Unable to start activity ComponentInfo{dk.itu.sortinggarbageapp/dk.itu.sortinggarbageapp.GarbageActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.Map.put(java.lang.Object, java.lang.Object)' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7656)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
 Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.Map.put(java.lang.Object, java.lang.Object)' on a null object reference
    at dk.itu.sortinggarbageapp.ItemsDB.addItem(ItemsDB.java:27)
    at dk.itu.sortinggarbageapp.ItemsDB.fillItemsDB(ItemsDB.java:40)
    at dk.itu.sortinggarbageapp.ItemsDB.<init>(ItemsDB.java:17)
    at dk.itu.sortinggarbageapp.ItemsDB.get(ItemsDB.java:21)
    at dk.itu.sortinggarbageapp.GarbageActivity.onCreate(GarbageActivity.java:24)
    at android.app.Activity.performCreate(Activity.java:8000)
    at android.app.Activity.performCreate(Activity.java:7984)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:223) 
    at android.app.ActivityThread.main(ActivityThread.java:7656) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.ja va:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
I/Process: Sending signal. PID: 8926 SIG: 9
Disconnected from the target VM, address: 'localhost:63608',transport: 
'socket'

Solution

  • The ItemsDB constructor used when the activity is started calls fillItemsDB() which adds items to the ItemsDB field. However, that field is not initialized in this constructor.

    You need to either initialize it there, call the other constructor, or initialize where you declare the field.

    // initialize at field declaration
    Map<String, Item> ItemsDB = new HashMap<>();
    
    // initialize here
    private ItemsDB(Context context)  {
        ItemsDB = new HashMap<>();
        fillItemsDB();
    }
    // call the other constructor
    public ItemsDB(Context context) {
        this();
        fillItemsDB();
    }
    

    Either of these things will work.