Solution 1 :
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()
}
}
}
Solution 2 :
You need to override onSaveInstanceState and onRestoreInstanceState example follows
class MainActivity : AppCompatActivity() {
private lateinit var resultTv: TextView
private var count = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val buttonIncrease = findViewById<Button>(R.id.button_increase)
val buttonDecrease = findViewById<Button>(R.id.button_decrease)
resultTv = findViewById(R.id.result)
buttonIncrease.setOnClickListener { view ->
updateValue(view.id)
resultTv.text = "" + count
}
buttonDecrease.setOnClickListener { view ->
updateValue(view.id)
resultTv.text = "" + count
}
}
private fun updateValue(id: Int) {
if (id == R.id.button_increase) {
if (count < 10) count++
} else {
if (count > 0) count--
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putInt("count", count)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState)
savedInstanceState?.let {
count = it.get("count") as Int
resultTv.text = "" + count
}
}
}
Problem :
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
Comments
Comment posted by stackoverflow.com/help/how-to-ask
Please provide more info about your problem. Saving state code is necessary and the excact exception or problem description. Please consider reading
Comment posted by ibrahim shaffee
Its not working, is there an alternate way to do this
Comment posted by iknow
Strange, I have tested it and it always saves count value in the TextView. I don’t know if there is another way. Maybe ViewModel?
Comment posted by ibrahim shaffee
if its ok, can you tell me how to do it in view model
Comment posted by iknow
@ibrahimshaffee I have added a full view model example. If it is working (it has to) You can upvote and accept my answer
Comment posted by developer.android.com/guide/components/activities/…
Am I correct in assuming the Google documentation is wrong here
Comment posted by Jonathan
Was this code tested, or copied from another website? Are you sure the parameter type is
Comment posted by Mbuodile Obiosio
@Jonathan the question mark is a null-safe check in Kotlin. Meaning if savedInstanceState is not null.
Comment posted by Jonathan
Yup, that’s it’s purpose. I can’t recall the specific detail, as its near a year old, but I do recall when I tested this code in the IDE it would not work with the null check – not sure why, but I know removing it made a difference to the compiler back then!