Ejemplo de LiveData en Kotlin

Ejemplo de uso de LiveData en Kotlin

Patrón Observer

Descripción general de LiveData

Código en Github: LiveData Demo Project

Crear un nuevo proyecto en Kotlin llamado LiveDataDemoProject

– Usar view binding

build.gradle:

buildFeatures {
    viewBinding = true
}

Dependencias en Build.gradle (del módulo)

Dependencias del ciclo de vida

// ViewModel
implementation(libs.androidx.lifecycle.viewmodel.ktx)
// LiveData
implementation(libs.androidx.lifecycle.livedata.ktx)

activity_main.xml

<?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/number_txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:text="0"
        android:textSize="70sp"
        android:textStyle="bold"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/number_input"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:ems="10"
        android:inputType="number"
        android:hint="Milliseconds"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/number_txt" />

    <Button
        android:id="@+id/start_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Start"
        android:textAllCaps="false"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/number_input" />

    <Button
        android:id="@+id/stop_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:text="Stop"
        android:textAllCaps="false"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/start_btn" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivityViewModel.kt

class MainActivityViewModel: ViewModel() {

    private lateinit var timer: CountDownTimer

    /** timerValue - LiveData object. We are going to set this value from MainActivity */
    var timerValue = MutableLiveData<Long>()

    /** Finished - LiveData object. This value is being observer from MainActivity
     * Here I'm using a variable to get a private MutableLiveData value */
    private var _finished = MutableLiveData<Boolean>()
    val finished: LiveData<Boolean>
        get() = _finished

    /** Seconds - LiveData object. This value is being observer from MainActivity
     * Here I'm using a function to get a private MutableLiveData value */
    private val _seconds = MutableLiveData<Int>()
    fun seconds(): LiveData<Int>{
        return _seconds
    }

    /** Start Timer. This function is triggered from MainActivity. */
    fun startTimer(){
        timer = object : CountDownTimer(timerValue.value!!.toLong(), 1000){
            override fun onFinish() {
                _finished.value = true
            }

            override fun onTick(p0: Long) {
                val timeLeft = p0/1000
                _seconds.value = timeLeft.toInt()
            }
        }.start()
    }

    /** Stop Timer. This function is triggered from MainActivity. */
    fun stopTimer(){
        timer.cancel()
    }

}

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //setContentView(R.layout.activity_main)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val viewModel = ViewModelProvider(this).get(MainActivityViewModel::class.java)

        /** Observing seconds() LiveData object from ViewModel */
        viewModel.seconds().observe(this, Observer {
            binding.numberTxt.text = it.toString()
        })
        /** Observing finished LiveData object from ViewModel */
        viewModel.finished.observe(this, Observer {
            if(it){
                Toast.makeText(this, "Finished!", Toast.LENGTH_SHORT).show()
            }
        })

        binding.startBtn.setOnClickListener {
            if (binding.numberInput.text.isEmpty() || binding.numberInput.text.length < 4){
                Toast.makeText(this, "Invalid Number", Toast.LENGTH_SHORT).show()
            }else{
                viewModel.timerValue.value = binding.numberInput.text.toString().toLong()
                viewModel.startTimer()
            }

        }
        binding.stopBtn.setOnClickListener {
            binding.numberTxt.text = "0"
            viewModel.stopTimer()
        }

    }
}

 

Deja una respuesta