Reputation: 35
package com.example.absolutelydumb
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.InputType
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*
//sets var to some random number and asks for a guess, giving feedback on proximity to answer
class MainActivity : AppCompatActivity() {
private val startButton: Button = findViewById(R.id.startButton)
private val submitButton: Button = findViewById(R.id.submit)
private val instructionsText: TextView = findViewById(R.id.instructionView)
private val response: EditText = findViewById(R.id.answerInput)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val startText: String = getString(R.string.startText)
startButton.text = startText
//TODO("Add autofillHints")
startButton.setOnClickListener {
numberGuess()
}
//TODO("Set text back to start after guessing is done")
}
fun numberGuess() {
response.inputType = InputType.TYPE_CLASS_NUMBER
val clickText: String = getString(R.string.clickText)
startButton.text = clickText
//TODO("Add autofillHints")
instructionsText.text = getString(R.string.instructions)
val randomNumber: Int = rand(0,10)
submitButton.setOnClickListener {
val responseText = Integer.parseInt(answerInput.text.toString())
if(responseText == randomNumber) {
instructionsText.text = getString(R.string.correctGuess)
} else {
instructionsText.text = getString(R.string.badGuess)
}
}
}
fun rand(start: Int, end: Int): Int {
//require(start <= end) { "Illegal Argument" }
return (start..end).random()
}
}
Above is the code that I've been writing. This is my first project, so I don't know what went wrong. I fixed a variable type problem in the numberGuess function but when I finished fixing it the app wouldn't open and the virtual device stated a "app keeps stopping" error.
Here is the Run log that lists off errors. The build log didn't have any errors.
07/09 19:58:05: Launching 'app' on phone1.
Install successfully finished in 1 s 266 ms.
$ adb shell am start -n "com.example.absolutelydumb/com.example.absolutelydumb.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 5935 on device 'phone1 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.absolutelydumb, PID: 5935
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.absolutelydumb/com.example.absolutelydumb.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2843)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:159)
at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:157)
at android.content.Context.obtainStyledAttributes(Context.java:675)
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:692)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:659)
at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:479)
at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:214)
at com.example.absolutelydumb.MainActivity.<init>(MainActivity.kt:13)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2831)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Upvotes: 0
Views: 898
Reputation: 93521
You cannot call findViewById
before onCreate()
or setContentView()
is called. Since you are using findViewById
at the declaration site of your four properties, it is being called at the time your Activity class is being instantiated, which is before onCreate
is called.
There are two ways to handle this.
lateinit var
and set the properties right after your call to setContentView()
:private lateinit var startButton: Button
//...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = findViewById(R.id.startButton)
//...
by lazy
so it is only called when the property is first accessed, which will be after setContentView()
is called:private val startButton: Button by lazy { findViewById(R.id.startButton) }
Or you can use view binding, which gets rid of most of this boilerplate and is less error-prone. By error-prone, I mean you can call findViewById
and accidentally search for a view that isn't present in the current layout and it will crash at runtime. View binding makes this impossible.
Upvotes: 2