Taylor
Taylor

Reputation: 3

java.lang.RuntimeException: Unable to instantiate activity error when trying to switch between activities

I am new at this and I am trying to transition from a fragment to a new activity using a button to add data into shared preferences and display it in a list view in the fragment (it's part of MainActivity). When I click on the floating button, I get the error:

{java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.calculator3dprinting/com.example.calculator3dprinting.PrinterAddActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference}

Here is the fragment and the activity I want to switch to

import android.content.Context.MODE_PRIVATE
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.fragment.app.Fragment
import com.google.android.material.floatingactionbutton.FloatingActionButton


class PrinterFragment: Fragment() {
    private val TAG = "PrinterFragment"
    private lateinit var pMap: PrinterManager
    private lateinit var mListView: ListView
    private lateinit var sharedPreferences: SharedPreferences
    //private val db = DatabaseManager()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.printer_fragment, container, false)
        mListView = view.findViewById(R.id.ListView)

        val newPrinter: FloatingActionButton = view.findViewById(R.id.addPrinter)
        newPrinter.setOnClickListener {
            val intent = Intent(this.context, PrinterAddActivity::class.java)
            startActivity(intent)
        }

        //AsyncTask.execute() {
        populateListView(mListView, view)
        //}
        return view
    }

    private fun populateListView(mListView: ListView, view: View) {
        /*
        db.context = view.context
        db.initialize()

        val data = db.getPrinterNames()

        val adapter = ArrayAdapter(
            view.context, android.R.layout.simple_list_item_1, data
        )
        mListView.adapter = adapter

        mListView.onItemClickListener =
            OnItemClickListener { adapterView, _, i, _ ->
                val name = adapterView.getItemAtPosition(i).toString()
                Log.d(TAG, "onItemClick: You Clicked on $name")

                val itemId = db.getPrinterIdByName(name) //get the id associated with that name

                Log.d(TAG, "onItemClick: The ID is: $itemId")
                val editScreenIntent =
                    Intent(view.context, PrinterEditActivity::class.java)
                editScreenIntent.putExtra("id", itemId)
                startActivity(editScreenIntent)

            }
    }
    */
        sharedPreferences = requireContext().getSharedPreferences("Printers", MODE_PRIVATE)
        pMap = PrinterManager(sharedPreferences.all as MutableMap<Int, PrinterManager.Printers>)

        val pList = pMap.hashPrinter.values.toList()
        val adapter = ArrayAdapter(view.context, android.R.layout.simple_list_item_1, pList)
        mListView.adapter = adapter

        mListView.onItemClickListener =
            AdapterView.OnItemClickListener { adapterView, _, i, _ ->
                val name = adapterView.getItemAtPosition(i).toString()
                Log.d(TAG, "onItemClick: You Clicked on $name")

                val itemId = pMap.getIdByName(name) //get the id associated with that name

                Log.d(TAG, "onItemClick: The ID is: $itemId")
                val editScreenIntent =
                    Intent(view.context, PrinterEditActivity::class.java)
                editScreenIntent.putExtra("id", itemId)
                startActivity(editScreenIntent)
            }
    }
}
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class PrinterAddActivity: AppCompatActivity() {
    //private val db = DatabaseManager()
    private lateinit var pMap: PrinterManager
    private val sharedPreferences: SharedPreferences
            = applicationContext.getSharedPreferences("Printers", MODE_PRIVATE)
    private val editor = sharedPreferences.edit()


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_printer_add)

        val savePrinter: Button = findViewById(R.id.save_printerBtn)
        val backButton: Button = findViewById(R.id.back_printer)

        val editName: EditText = findViewById(R.id.pAdd_name)
        val editDiam: EditText = findViewById(R.id.materialAdd_diameter)
        val editPrice: EditText = findViewById(R.id.pAdd_price)
        val editDepH: EditText = findViewById(R.id.depreciationAdd_time)
        val editSvc: EditText = findViewById(R.id.serviceAdd_costs)
        val editEnergy: EditText = findViewById(R.id.energyAdd_consumption)


        savePrinter.setOnClickListener {
            val id: Int
            val item1 = editName.text.toString()
            val item2 = editDiam.text.toString().toDouble()
            val item3 = editPrice.text.toString().toDouble()
            val item4 = editDepH.text.toString().toDouble()
            val item5 = editSvc.text.toString().toDouble()
            val item6 = editEnergy.text.toString().toDouble()

            //AsyncTask.execute() {
            if (item1 != "" || !item3.equals(null)
                || !item4.equals(null) || !item6.equals(null)
            ) {
                id = pMap.addPrinterAndGetId(item1, item2, item3, item4, item5, item6)
                editor.putStringSet(id.toString(), pMap.toMutableString(pMap.getPrinterById(id)))
                editor.commit()
            } else {
                Toast.makeText(
                    this, "Important Fields have not been filled out",
                    Toast.LENGTH_SHORT
                ).show()
            }
            //}
        }

        backButton.setOnClickListener {
            val i = Intent(this, MainActivity::class.java)
            startActivity(i)
        }
    }
}

Here are the errors:

2020-12-03 21:58:27.983 20229-20229/com.example.calculator3dprinting E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.calculator3dprinting, PID: 20229
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.calculator3dprinting/com.example.calculator3dprinting.PrinterAddActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3194)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        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:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
        at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:118)
        at com.example.calculator3dprinting.PrinterAddActivity.<init>(PrinterAddActivity.kt:15)
        at java.lang.Class.newInstance(Native Method)
        at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
        at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1243)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3182)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        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:2016) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

I appreciate any feedback you can give :)

Upvotes: 0

Views: 1652

Answers (1)

cactustictacs
cactustictacs

Reputation: 19544

The stacktrace (the error report thing) reads backwards - the top line tells you the error, and the series of calls that led to it. It's split into sections, so the second Caused by part tells you what caused the error above it. It's saying you tried to call:

android.content.Context.getApplicationContext()

on a null reference - i.e. you tried to call getApplicationContext() on something that should be a Context but was actually null.

A couple of lines down (stepping back through the things that caused the crash) it says you were in the initialisation block of PrinterAddActivity, and tells you the line number (PrinterAddActivity.kt:15). That's where yr problem is


That was just showing you how to work out where problems might be coming from! Basically your issue is you're referring to applicationContext (which is really getApplicationContext() in Kotlin) when you initialise val sharedPreferences - but your Activity doesn't have a context when you first create it. That shows up later in its lifecycle, so it's null at the point you're trying to access it.

This is probably a good candidate for a lazy delegate

private val sharedPreferences: SharedPreferences by lazy { applicationContext.getSharedPreferences("Printers", MODE_PRIVATE) }

Same thing really, except it gets initialised lazily, when it's first accessed - ideally you'll be doing that when the Activity has its context, like from onCreate onwards! Which you're currently not - editor references it when that gets initialised. So you'll either need to wrap that in a lazy too, but you could just ditch it altogether and call edit() when you're doing an edit

Upvotes: 1

Related Questions