javaandroidandroid-studiokotlinonsaveinstancestate

save Instance State in Android studio: Kotlin


I was doing this program and tried to run an app as an output. However, when I turned the app in Landscape mode, my text output didn't work. I realized that I need to add onSaveInstanceState in the Kotlin code, which I don't know how to do.

MainActivity.kt:

class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        var count = 10
        val textCount = findViewById<View>(R.id.textView) as TextView
        val buttonred = findViewById<View>(R.id.injury) as Button
        val buttoning = findViewById<View>(R.id.vial) as Button

        buttonred.setOnClickListener {
            if (count >= 0) {
                count--
                textCount.text = count.toString()
            }
        }

        buttoning.setOnClickListener {
            if (count <= 10)
                count += 3
            textCount.text = count.toString()
        }
    }
}

XML Code

LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

<TextView
        android:id="@+id/textView"
        android:layout_width="60dp"
        android:layout_height="78dp"
        android:layout_marginStart="145dp"
        android:layout_marginTop="68dp"
        android:layout_marginEnd="145dp"
        android:textSize="50dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
<Button
        android:id="@+id/injury"
        android:layout_width="106dp"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="150dp"
        android:text="injury"
         />
<Button
        android:id="@+id/vial"
        android:layout_width="197dp"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="109dp"
        android:text="vial" />
</LinearLayout>

I would like to know how to add the onSaveInstanceState


Solution

  • Here is the full code, You didn't add many details but this is how the sample project looks, it enables to save count and then set it to TextView:

    MainActivity.kt:

    import android.os.Bundle
    import android.util.Log
    import androidx.appcompat.app.AppCompatActivity
    import kotlinx.android.synthetic.main.activity_main.*
    
    class MainActivity : AppCompatActivity() {
    
        companion object {
            const val COUNT_KEY = "COUNT_KEY" // const key to save/read value from bundle
        }
        
        private var count = 0 // count value with setter. It will be easier, You can change this value and don't have to think about setting TextView.text
            set(value) {
                field = value
                txtCount.text = value.toString()
            }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            Log.i("MyTag", "onCreate")
    
            txtCount.text = count.toString()
    
            butIncrement.setOnClickListener {
                count++
            }
    
        }
    
        override fun onSaveInstanceState(outState: Bundle) { // Here You have to save count value
            super.onSaveInstanceState(outState)
            Log.i("MyTag", "onSaveInstanceState")
            
            outState.putInt(COUNT_KEY, count)
        }
    
        override fun onRestoreInstanceState(savedInstanceState: Bundle) { // Here You have to restore count value
            super.onRestoreInstanceState(savedInstanceState)
            Log.i("MyTag", "onRestoreInstanceState")
    
            count = savedInstanceState.getInt(COUNT_KEY)
        }
    }
    

    activity_main.xml:

    <androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <Button
            android:id="@+id/butIncrement"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Increment" />
    
        <TextView
            android:id="@+id/txtCount"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="40sp" />
    
    </androidx.appcompat.widget.LinearLayoutCompat>
    

    You edited the question and added more details, here is the full Kotlin code, I tested it and it seems to work.

    import android.os.Bundle
    import android.util.Log
    import android.view.View
    import android.widget.Button
    import android.widget.TextView
    import androidx.appcompat.app.AppCompatActivity
    
    class MainActivity : AppCompatActivity() {
    
        lateinit var textCount: TextView
        lateinit var buttonred: Button
        lateinit var buttoning: Button
    
        companion object {
            const val COUNT_KEY = "COUNT_KEY"
        }
    
        private var count = 0
            set(value) {
                field = value
                textCount.text = value.toString()
            }
    
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            Log.i("MyTag", "onCreate")
    
    
            textCount = findViewById<View>(R.id.textView) as TextView
            buttonred = findViewById<View>(R.id.injury) as Button
            buttoning = findViewById<View>(R.id.vial) as Button
    
            count = 10
    
            buttonred.setOnClickListener {
                if (count >= 0) {
                    count--
                    textCount.text = count.toString()
                }
            }
    
            buttoning.setOnClickListener {
                if (count <= 10)
                    count += 3
                textCount.text = count.toString()
            }
        }
    
        override fun onSaveInstanceState(outState: Bundle) {
            super.onSaveInstanceState(outState)
            Log.i("MyTag", "onSaveInstanceState")
    
            outState.putInt(COUNT_KEY, count)
        }
    
        override fun onRestoreInstanceState(savedInstanceState: Bundle) {
            super.onRestoreInstanceState(savedInstanceState)
            Log.i("MyTag", "onRestoreInstanceState")
    
            count = savedInstanceState.getInt(COUNT_KEY)
        }
    }
    

    ViewModel implementation:

    To Your Gradle (module.app) file add:

    dependencies {
        def lifecycle_version = "2.2.0"
    
        // ViewModel
        implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
        // LiveData
        implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    }
    

    MainActivityViewModel class:

    import androidx.lifecycle.LiveData
    import androidx.lifecycle.MutableLiveData
    import androidx.lifecycle.ViewModel
    
    
    internal class MainActivityViewModel : ViewModel() {
    
        private val _count: MutableLiveData<Int> = MutableLiveData()
        val count: LiveData<Int>
            get() = _count
    
        init {
            _count.value = START_VALUE
        }
    
        fun increment() {
            _count.value = _count.value!! + 1
        }
    
        fun decrement() {
            _count.value = _count.value!! - 1
    
        }
    
        companion object {
            private const val START_VALUE = 10
        }
    }
    

    MainActivity class:

    import android.os.Bundle
    import android.view.View
    import android.widget.Button
    import android.widget.TextView
    import androidx.appcompat.app.AppCompatActivity
    import androidx.lifecycle.ViewModelProvider
    
    class MainActivity : AppCompatActivity()
    {
        private lateinit var viewModel: MainActivityViewModel
    
        lateinit var textCount: TextView
        lateinit var butIncrement: Button
        lateinit var butDecrement: Button
    
        override fun onCreate(savedInstanceState: Bundle?)
        {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            textCount = findViewById<View>(R.id.textView) as TextView
            butIncrement = findViewById<View>(R.id.injury) as Button
            butDecrement = findViewById<View>(R.id.vial) as Button
    
            viewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)
    
            viewModel.count.observe(this, {
                textCount.text = it.toString()
            })
    
            butIncrement.setOnClickListener {
                viewModel.increment()
            }
    
            butDecrement.setOnClickListener {
                viewModel.decrement()
            }
        }
    }