Sobes.tech
Middle

Como implementar um mecanismo de cache de dados numa aplicação Android?

sobes.tech IA

Resposta da IA

O mecanismo de cache no Android pode ser implementado de várias formas, escolhendo a mais adequada dependendo do tipo de dados e do seu ciclo de vida.

Abordagens principais:

  • Armazenamento interno (Internal Storage): Adequado para dados sensíveis, acessíveis apenas pela aplicação. Os dados são armazenados num diretório privado para a aplicação.
  • Armazenamento externo (External Storage): Utilizado para dados menos sensíveis, que podem ser lidos por outras aplicações ou utilizadores. Requer permissões.
  • Preferências partilhadas (Shared Preferences): Ideal para armazenar pequenos volumes de dados simples "chave-valor", como configurações da aplicação.
  • Bases de dados SQLite: Solução poderosa para dados estruturados, permitindo realizar consultas complexas. O Android oferece suporte integrado para SQLite.
  • Pasta de cache: Destinada especificamente a dados temporários. O sistema pode eliminar estes ficheiros se precisar de libertar espaço.

Exemplo de uso do armazenamento interno para cache:

// Obter ficheiro de cache
val cacheFile = File(context.cacheDir, "my_cached_data.txt")

// Escrever dados no cache
try {
    FileOutputStream(cacheFile).use { fos ->
        fos.write("Dados para cache".toByteArray())
    }
} catch (e: IOException) {
    // Gerir erro
}

// Ler dados do cache
try {
    FileInputStream(cacheFile).use { fis ->
        val data = fis.readBytes().toString(Charsets.UTF_8)
        // Utilizar dados em cache
    }
} catch (e: IOException) {
    // Gerir erro, possivelmente o cache está vazio ou inacessível
}

// Eliminar ficheiro de cache
cacheFile.delete()

Exemplo de uso de Shared Preferences:

// Obter instância de Shared Preferences
val sharedPref = context.getSharedPreferences("my_cache_prefs", Context.MODE_PRIVATE)

// Escrever dados
with(sharedPref.edit()) {
    putString("cached_key", "cached_value")
    apply()
}

// Ler dados
val cachedValue = sharedPref.getString("cached_key", null)
// Utilizar cachedValue

// Eliminar dados
with(sharedPref.edit()) {
    remove("cached_key")
    apply()
}

Para trabalhar com SQLite, muitas vezes são usadas bibliotecas de envolvimento como o Room, que faz parte dos Componentes de Arquitetura do Android.

// Exemplo de uso do Room: definição de entidade
@Entity(tableName = "users")
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val age: Int?
)

Estratégias de cache:

  • Cache-Aside: A aplicação verifica primeiro o cache. Se os dados forem encontrados, são utilizados. Caso contrário, os dados são carregados da fonte (por exemplo, rede) e depois colocados no cache para futuras consultas.
  • Read-Through: A biblioteca ou framework (por exemplo, OkHttp para requisições de rede) gerencia automaticamente o cache. Ao solicitar dados, a biblioteca verifica o cache, e se os dados estiverem ausentes ou desatualizados, os carrega da fonte e atualiza o cache.
  • Write-Through: Os dados são primeiro gravados no cache, e depois simultaneamente na fonte principal.
  • Write-Back: Os dados são primeiro gravados apenas no cache. As alterações são posteriormente transferidas para a fonte principal (por exemplo, base de dados) mais tarde, possivelmente ao preencher o cache ou de acordo com uma programação.

A escolha da estratégia e do método de cache depende dos requisitos de atualidade dos dados, desempenho e volume de dados armazenados. É também importante considerar o TTL (Time To Live) dos dados em cache para garantir a sua atualidade.