Flutter — O que é e como utilizar o banco de dados hive

Vinicius Santos
Flutter — Comunidade BR
6 min readOct 3, 2019

Hive é um banco de dados do tipo chave-valor, leve e extremamente rápido feito em Dart puro. Essa é a descrição que você encontra no pub.dev e documentação do projeto.

Como o hive trabalha

O hive utiliza o conceito de caixas para armazenar os dados. Uma caixa pode ser comparada com uma tabela do SQL, mas as caixas não tem uma estrutura fixa e podem conter qualquer coisa.

Vantagens

O hive se apresenta como uma opção extremamente vantajosa em relação as outras opções de persistência de dados no Flutter, o conhecido shared_preferences e o SQLite por dois motivos:

O primeiro, atualmente o shared_preferences não funciona na plataforma web pois encapsula os nativos NSUserDefaults no iOS e SharedPreferences no Android.

E o segundo, o desempenho do hive é muito superior ao SQLite tanto em leitura quanto escrita. Em relação ao shared_preferences, os dois são equiparáveis em leitura, porém o hive ganha na escrita.

Benchmark apresentado na documentação

A diferença na escrita é bem grande, mas você não precisa acreditar nos resultados apresentados na documentação, você mesmo pode executar o benchmark.

Como executar o benchmark

Para fazer o benchmark primeiro faça um git clone do repositório:

git clone https://github.com/hivedb/hive_benchmark

Para executar o projeto você precisa do NDK. A instalação é bem simples e pode ser feita através do Android Studio.

Vá em SDK Manager, na aba SDK Tools e selecione:

LLDB
NDK
CMake
Instalação NDK

Após isso você precisa da variável de ambiente ANDROID_NDK_HOME.

Linux

Se você usa Linux e seguiu o meu artigo de instalação do Flutter você sabe que precisa ir até o diretório home e editar o arquivo .bashrc:

cd $home
sudo nano .bashrc

E adicione no final do arquivo a linha:

export ANDROID_NDK_HOME=/home/vinicius/Android/Sdk/ndk/versao

No meu caso fica assim:

export ANDROID_NDK_HOME=/home/vinicius/Android/Sdk/ndk/20.0.5594570
.bashrc

Aperte CTRL-X para sair, Y para salvar e ENTER para fechar.

Depois, ainda no diretório home execute a linha:

source .bashrc

Windows 10

Se você utiliza o Windows 10 vá até Painel de Controle > Sistema e Segurança > Sistema, depois clique em Configurações avançadas do sistema.

Depois clique em Variáveis de Ambiente. Clique duas vezes em Path, clique em novo e insira o caminho da pasta do NDK e clique em Ok.

Depois de configurar a variável de ambiente você pode abrir o projeto no Android Studio e ir em File > Project Structure pra confirmar se a localização do NDK está correta no projeto.

Android Studio
Project Structure

Depois disso você já conseguirá executar o benchmark.

Meus resultados

No projeto do benchmark nós temos as mesmas opções de Read, Write e adicionalmente a Delete.

Também temos cinco comparações:

Hive

Hive Lazy

SQLite

Shared_Preferences

SQLite com moor_ffi

Aqui estão os resultados que eu tive utilizando um aparelho muito mais fraco que o usado no benchmark da documentação:

A diferença entre o hive e SQLite parece ser menor nos meus resultados, porém devemos lembrar que o tempo no aparelho usado é muito maior, chegando a 53832ms, enquando no benchmark da documentação o tempo máximo é 14760ms.

Como utilizar

Agora que já ficou comprovado o desempenho do hive vamos conferir como utilizá-lo.

Crie um projeto

Primeiro crie um projeto padrão do flutter.

Adicionando hive no projeto

Em pubspec.yaml adicione:

dependencies:
hive: ^1.0.0
path_provider: ^1.2.0
dev_dependencies:
hive_generator: ^0.5.1
build_runner: ^1.7.1

Nós precisamos além do hive, incluir o path_provider para podermos pegar o diretório atual do aplicativo.

Agora apague todo o conteúdo do arquivo main.dart e inclua uma estrutura básica de um StatelessWidget:

import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart';
void main() => runApp(MaterialApp(home: MyApp()));class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Exemplo hive',
home: Container()
);
}
}

Agora vamos criar uma função para pegar os dados de uma caixa:

Future _abrirCaixa() async {  
var dir = await getApplicationDocumentsDirectory();
Hive.init(dir.path);
return await Hive.openBox('minhaCaixa');
}

Como essa operação envolve a leitura de um arquivo você precisa utilizar o modificador async e usar o await.

Se você estiver utilizando o flutter web você não precisa do path_provider no projeto e também não precisa utilizar o Hive.init().

Nós vamos utilizar um FutureBuilder pra criar a estrutura do nosso projeto. No future será utilizado a função _abrirCaixa, se algo der errado nós vamos exibir um Center com essa mensagem, se estiver tudo ok retornaremos nossa página principal.

Altere a classe MyApp:

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Exemplo hive',
home: FutureBuilder(
future: _abrirCaixa(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.error != null) {
return Scaffold(
body: Center(
child: Text('Algo deu errado :('),
),
);
} else {
return MinhaPagina();
}
} else {
return CircularProgressIndicator();
}
},
),
);
}
}

Agora nós vamos criar o widget MinhaPagina:

class MinhaPagina extends StatefulWidget {
@override
_MinhaPaginaState createState() => _MinhaPaginaState();
}
class _MinhaPaginaState extends State<MinhaPagina> {
Box _caixa;
@override
void initState() {
_caixa = Hive.box('minhaCaixa');
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Exemplo hive'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Reinicie o aplicativo para testar'),
SizedBox(height: 8),
Text('You have pushed the button this many times:'),
WatchBoxBuilder(
box: _caixa,
builder: (context, box) {
return Text(
box.get('contador', defaultValue: 0).toString(),
style: Theme.of(context).textTheme.display1,
);
},
),],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_caixa.put(
'contador',
_caixa.get('contador', defaultValue: 0) + 1);
},
tooltip: 'Aumentar',
child: Icon(Icons.add),
),);
}}

Para exibir o valor do contador nós vamos utilizar um widget criado pelo desenvolvedor do hive. O WatchBoxBuilder se recria toda vez que o valor de uma caixa ou de uma chave específica muda.

Para usar vamos inserir no pubspec.yaml:

dependencies:
hive: ^1.0.0
path_provider: ^1.2.0
hive_flutter: any
dev_dependencies:
hive_generator: ^0.5.1
build_runner: ^1.7.1

Depois adicione o import em main.dart:

import 'package:hive_flutter/hive_flutter.dart';

Sempre que o aplicativo é iniciado ele lê o valor de contador e exibe na tela. Sempre que o botão é pressionado o valor também é atualizado na caixa, o que faz com que o WatchBoxBuilder seja atualizado.

Esse é um exemplo bem simples porém já consegue mostrar um pouco de como utilizar o hive. Ele aparenta ser uma ótima opção de persistência no flutter, com um desempenho excelente e sem dependências nativas.

Esse projeto foi baseado na documentação do hive e pode ser encontrado no Github.

--

--