steelscape02
steelscape02

Reputation: 35

Android Studio kotlin app "keep stopping" error

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

Answers (1)

Tenfour04
Tenfour04

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.

  1. Use 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)
    //...
  1. Use 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

Related Questions