I have made a Body mass index-calculator using ViewModel and LiveData.
Source-code of the MainActivity:
package com.example.bmirechner
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.SeekBar
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.bmirechner.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: BmiViewModel
fun updateUi() {
val bmi = viewModel.computeBmi()
binding.resultTextView.text = bmi.toString()
var messageText = ""
when {
bmi < 20 -> messageText = resources.getString(R.string.text_underweight)
bmi in 20.0..25.0 -> messageText = resources.getString(R.string.text_normal_weight)
bmi > 25 && bmi <= 30 -> messageText = resources.getString(R.string.text_overweight)
bmi > 30 -> messageText = resources.getString(R.string.text_heavy_overweight)
else -> messageText = resources.getString(R.string.error)
}
binding.messageTextView.text = messageText
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(this).get(BmiViewModel::class.java)
binding.currentWeightTextView.text = viewModel.getCurrentWeight().value.toString()
binding.currentHeightTextView.text = viewModel.getCurrentHeight().value.toString()
binding.heightSeek.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
viewModel.setCurrentHeight(progress.toDouble())
viewModel.getCurrentHeight().observe(this@MainActivity, Observer {
binding.currentHeightTextView.text = it.toString()
})
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
updateUi()
}
})
binding.weightSeek.setOnSeekBarChangeListener(object: SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
viewModel.setCurrentWeight(progress.toDouble())
viewModel.getCurrentWeight().observe(this@MainActivity, Observer {
binding.currentWeightTextView.text = it.toString()
})
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
updateUi()
}
})
}
}
Source-Code of the ViewModel:
package com.example.bmirechner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlin.math.pow
import kotlin.math.round
class BmiViewModel: ViewModel() {
private var currentHeight = MutableLiveData<Double>()
private var currentWeight = MutableLiveData<Double>()
init {
currentHeight.value = 0.0
currentWeight.value = 0.0
}
fun setCurrentHeight(value: Double) {
currentHeight.value = value
}
fun setCurrentWeight(value: Double) {
currentWeight.value = value
}
fun getCurrentHeight(): MutableLiveData<Double> {
return currentHeight
}
fun getCurrentWeight(): MutableLiveData<Double> {
return currentWeight
}
fun computeBmi(): Double {
val factor = 10
val heightInMeter = currentHeight.value!! / 100.0
val bmi = currentWeight.value!! / heightInMeter.pow(2)
return round(bmi * factor) / factor
}
}
Is my LiveData-usage correct or should it be modified?
What parts of my implementation could be improved?
Looking forward to reading your comments and answers.