I have two activities in my app. In Activity A (MainActivity.kt) I have two buttons named buttonGo
and buttonCounter
. If I click on buttonGo
it will go to another activity B (Second.kt). What I want to achieve is, everytime I click on buttonCounter
the textCounter(Textview)
present in activity B should increment by 1. Currently, no increment takes place.
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var counterViewModel: CounterViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
counterViewModel = ViewModelProvider(this)[CounterViewModel::class.java]
binding.buttonGo.setOnClickListener {
val intent = Intent(this@MainActivity, Second::class.java)
startActivity(intent)
}
binding.buttonCounter.setOnClickListener {
counterViewModel.incrementCounter()
}
}
}
Second.kt
class Second:AppCompatActivity() {
private lateinit var counterViewModel: CounterViewModel
private lateinit var binding: SecondBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = SecondBinding.inflate(layoutInflater)
setContentView(binding.root)
counterViewModel = ViewModelProvider(this)[CounterViewModel::class.java]
binding.buttonBack.setOnClickListener {
onBackPressed()
}
counterViewModel.counter.observe(this, Observer {count ->
binding.textCounter.text = count.toString()
})
}
}
Below is my viewModel named CounterViewModel.kt
class CounterViewModel : ViewModel() {
private val _counter = MutableLiveData<Int>(0)
val counter: LiveData<Int> get() = _counter
fun incrementCounter() {
_counter.value = (_counter.value ?: 0) + 1
}
}
This is the layout file of MainActivity.kt
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button_Go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Go"
app:layout_constraintBottom_toTopOf="@+id/button_Counter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<Button
android:id="@+id/button_Counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Counter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_Go" />
</androidx.constraintlayout.widget.ConstraintLayout>
This is my layout file for Second.kt
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<TextView
android:id="@+id/textCounter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="@android:color/black"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Back"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textCounter" />
</androidx.constraintlayout.widget.ConstraintLayout>
I created a Viewmodel to observe the data changes, created a function for incrementing but the textCounter
is not incrementing from its initial value of 0.
You can't share a ViewModel across Activities. However, there are two ways to pass data between activities:
1.Intent : You can pass data between activities using Intent
. For example, you can pass the counter value from MainActivity to Second activity via Intent.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var counter = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.buttonGo.setOnClickListener {
val intent = Intent(this@MainActivity, Second::class.java)
intent.putExtra("counter", counter)
startActivity(intent)
}
binding.buttonCounter.setOnClickListener {
counter++
}
}
}
class Second : AppCompatActivity() {
private lateinit var binding: SecondBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = SecondBinding.inflate(layoutInflater)
setContentView(binding.root)
val counter = intent.getIntExtra("counter", 0)
binding.textCounter.text = counter.toString()
binding.buttonBack.setOnClickListener {
onBackPressed()
}
}
}
2.SharedPreferences : You can use SharedPreferences
to hold the counter data and retrieve it whenever the activity is recreated. This method persists data even if the app is closed.
CounterViewModel.kt
class CounterViewModel(application: Application) : AndroidViewModel(application) {
private val preferences = application.getSharedPreferences("counter_prefs", Context.MODE_PRIVATE)
private val _counter = MutableLiveData<Int>()
val counter: LiveData<Int> get() = _counter
init {
_counter.value = preferences.getInt("counter", 0)
}
fun incrementCounter() {
val newValue = (_counter.value ?: 0) + 1
_counter.value = newValue
preferences.edit().putInt("counter", newValue).apply()
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var counterViewModel: CounterViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
counterViewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(application))[CounterViewModel::class.java]
binding.buttonGo.setOnClickListener {
val intent = Intent(this@MainActivity, Second::class.java)
startActivity(intent)
}
binding.buttonCounter.setOnClickListener {
counterViewModel.incrementCounter()
}
}
}
Second.kt
class Second : AppCompatActivity() {
private lateinit var counterViewModel: CounterViewModel
private lateinit var binding: SecondBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = SecondBinding.inflate(layoutInflater)
setContentView(binding.root)
counterViewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(application))[CounterViewModel::class.java]
counterViewModel.counter.observe(this, Observer { count ->
binding.textCounter.text = count.toString()
})
binding.buttonBack.setOnClickListener {
onBackPressed()
}
}
}