Reputation: 3
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
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