Search code examples
androidandroid-layoutkotlinandroid-activity

Kotlin App, click on button to open a new activity -> IllegalStateException: findViewById must not be null


i am working with this bock "Learn Kotlin for Android Development" and reached chapter 9. I have now 2 activities. The MainActivity has a menue bar at the top with a info button. This button should open the StatisticsActiv.

The MainActivity.kt is using a function called onOptionsItemSelected which should be called after clicking on the info button at the menu bar and so the function 'openStatistics' which will write the activity in the intent. But that is not happening... instead i get the Exception: java.lang.IllegalStateException: findViewById(statisticsContainer) must not be null (the full exception is shown below)

AndroidManifext.xml

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".StatisticsActivity" />
    <activity
        android:name=".MainActivity"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value=".MainActivity" />
</application>

MainActivity.kt

class MainActivity : AppCompatActivity() {
    val rnd: RandomNumberGenerator = StdRandom()
    // or ... = RandomRandom()
    var started = false
    var number = 0
    var tries = 0
    var gameUser = GameUser(
        lastName = "Doe",
        firstName = "John",
        userName = "jdoe",
        birthday = "1900-01-01",
        registrationNumber = 0,
        userRank = 0.0
    )

    override
    fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)

        fetchSavedInstanceData(savedInstanceState)
        doGuess.setEnabled(started)
    }

    override
    fun onCreateOptionsMenu(menu: Menu): Boolean {
        val inflater: MenuInflater = menuInflater
        inflater.inflate(R.menu.menu_options, menu)
        return true
    }

    override
    fun onOptionsItemSelected(item: MenuItem): Boolean {
        val statisticsContainer = R.id.statisticsContainer
        val displayTextView: TextView = findViewById(statisticsContainer)
        openStatistics()
        displayTextView.text = "TEST"
        return super.onOptionsItemSelected(item)
    }

    private fun openStatistics() {
        val intent = Intent(this, StatisticsActivity::class.java)
        startActivity(intent)
    }

    override
    fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        putInstanceData(outState)
    }

}

i thought that if i click the info button at the menu bar, it should use the function 'onOptionsItemSelected' and so the function 'openStatistics' which will write the activity in the intent.

menue_options.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/statistics"
        android:icon="@android:drawable/ic_menu_info_details"
        android:title="@string/statistics.menu_title"
        app:showAsAction="ifRoom" />
</menu>

StatisticsActivity.kt onCreate function

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

        restoreData(savedInstanceState)
        showData(Statistics.getStatistics())
    }

the statistics container layout: activity_statistics.xml


<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/statisticsContainer"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".StatisticsActivity">
</TextView>

Exception after clicking the info button

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: kotlinforandroid.book.numberguess, PID: 5201
    java.lang.IllegalStateException: findViewById(statisticsContainer) must not be null
        at kotlinforandroid.book.numberguess.MainActivity.onOptionsItemSelected(MainActivity.kt:55)
        at android.app.Activity.onMenuItemSelected(Activity.java:3450)
        at androidx.fragment.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:384)
        at androidx.appcompat.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:219)
        at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
        at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
        at androidx.appcompat.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:64)
        at androidx.appcompat.widget.Toolbar$1.onMenuItemClick(Toolbar.java:207)
        at androidx.appcompat.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:781)
        at androidx.appcompat.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:840)
        at androidx.appcompat.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:158)
        at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:991)
        at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:981)
        at androidx.appcompat.widget.ActionMenuView.invokeItem(ActionMenuView.java:625)
        at androidx.appcompat.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:151)
        at android.view.View.performClick(View.java:6294)
        at android.view.View$PerformClick.run(View.java:24770)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Solution

  • solution

    override
    fun onOptionsItemSelected(item: MenuItem): Boolean {
        openStatistics()
        return super.onOptionsItemSelected(item)
    }
    
    private fun openStatistics() {
        val intent = Intent(this, StatisticsActivity::class.java)
        startActivity(intent)
    }