Saltar a contenido

SharedPreferences

Cuando necesitamos almacenar una cantidad limitada de datos, es adecuado utilizar la clase SharedPreferences.
Este mecanismo se emplea habitualmente para guardar configuraciones simples de la aplicación, como por ejemplo:

  • Preferencias visuales (colores, modo oscuro).
  • Nivel actual en un juego.
  • Valores iniciales de controles de entrada.
  • Datos básicos del usuario, como un nombre.

Las SharedPreferences están diseñadas para almacenar pequeñas cantidades de información mediante el modelo clave–valor.
Debe tratarse siempre de información no sensible, ya que Android genera un archivo XML sin cifrar donde se almacenan estos datos.

Nota

Aunque hoy se recomienda DataStore para nuevos desarrollos, SharedPreferences sigue siendo muy útil a nivel formativo.

Objetivo del proyecto

La aplicación tendrá el siguiente comportamiento:

  • Si no hay ningún nombre guardado, se solicitará al usuario que lo introduzca.
  • Si ya existe un nombre almacenado, se mostrará un saludo junto a un botón para borrarlo.
  • Al borrar el nombre, la aplicación vuelve al estado inicial.

Además, se introduce el patrón Singleton para centralizar el acceso a las preferencias.

Maquetación inicial

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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tvName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <EditText
        android:id="@+id/etName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="Escribe tu nombre"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <Button
        android:id="@+id/btnSaveValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Guardar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <Button
        android:id="@+id/btnDeleteValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Borrar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Clase Prefs

class Prefs(context: Context) {

    private val PREFS_NAME = "com.cursokotlin.sharedpreferences"
    private val SHARED_NAME = "shared_name"

    private val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)

    var name: String
        get() = prefs.getString(SHARED_NAME, "") ?: ""
        set(value) = prefs.edit().putString(SHARED_NAME, value).apply()
}

Singleton con Application

class SharedApp : Application() {

    companion object {
        lateinit var prefs: Prefs
    }

    override fun onCreate() {
        super.onCreate()
        prefs = Prefs(applicationContext)
    }
}

Añadir en AndroidManifest.xml:

<application
    android:name=".SharedApp"
    ... >

Lógica de la Activity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        configView()

        btnSaveValue.setOnClickListener {
            SharedApp.prefs.name = etName.text.toString()
            configView()
        }

        btnDeleteValue.setOnClickListener {
            SharedApp.prefs.name = ""
            configView()
        }
    }

    fun showProfile() {
        tvName.visibility = View.VISIBLE
        tvName.text = "Hola ${SharedApp.prefs.name}"
        btnDeleteValue.visibility = View.VISIBLE
        etName.visibility = View.INVISIBLE
        btnSaveValue.visibility = View.INVISIBLE
    }

    fun showGuest() {
        tvName.visibility = View.INVISIBLE
        btnDeleteValue.visibility = View.INVISIBLE
        etName.visibility = View.VISIBLE
        btnSaveValue.visibility = View.VISIBLE
    }

    fun configView() {
        if (isSavedName()) showProfile() else showGuest()
    }

    fun isSavedName(): Boolean {
        return SharedApp.prefs.name.isNotEmpty()
    }
}

Actividad

  • AC601. Realiza el ejemplo en Compose, realiza una investigación para poder replicarlo.