React Native permite que você crie aplicativos Android com aparência e comportamento nativos usando apenas JavaScript. Nesse caso, o React Native se encarrega de gerenciar o estado da interface do usuário e sincronizá-lo com os modelos. E, para nossa sorte, podemos usar o Couchbase Lite para adicionar sincronização e persistência a um aplicativo React Native. Neste tutorial, você aprenderá a criar um aplicativo simples para salvar documentos e replicá-los para Gateway de sincronização. Aqui estão os principais conceitos que você aprenderá:
- Criar um projeto básico com o Couchbase Lite Android e o Couchbase Lite Java Listener
- Integração do React Native em seu projeto
- Adição de modelos e componentes de interface do usuário com JavaScript
- Configuração do Couchbase Sync Gateway
Aqui está uma prévia do que você vai construir:
Você pode fazer o download do projeto concluído em GitHub.
Pré-requisitos
- Node.js 4.0 ou superior
- Estúdio Android e um emulador
Primeiros passos
Nesta seção, você criará um novo projeto do Android Studio do zero e integrar o React Native a ele.
Novo projeto do Android Studio
Antes de começar a escrever algum JavaScript, você precisa criar um novo projeto no Android Studio com todas as dependências. Abra o Android Studio e, na tela de boas-vindas, selecione Novo projeto. Na janela Novo projeto, digite TodoLite ReactNative Android para o nome do aplicativo e todolite-reactnative-android para o nome da pasta:
Defina o SDK mínimo necessário como API 16: Android 4.1 ou posterior e usar a API do Android recomendada atualmente. Depois de preencher os campos, a janela New Project deverá ter a seguinte aparência:
Clique em Next e escolha a opção Atividade em branco modelo:
Clique em Acabamento e você deverá ver o seguinte no navegador de projetos:
Agrupamento de dependências
Expanda a pasta do aplicativo e abra a pasta build.gradle arquivo. Certifique-se de abrir o arquivo localizado no diretório aplicativo (também chamada de módulo) e adicione o seguinte na pasta androide seção:
1 2 3 4 5 6 7 |
// solução alternativa para o problema de "arquivos duplicados durante o empacotamento do APK // consulte https://groups.google.com/d/msg/adt-dev/bl5Rc4Szpzg/wC8cylTWuIEJ packagingOptions { excluir 'META-INF/ASL2.0' excluir 'META-INF/LICENSE' excluir 'META-INF/NOTICE' } |
Em seguida, abra build.gradle na raiz (também chamado de arquivo gradle no nível do projeto) e adicione uma referência ao repositório Maven do Couchbase:
1 2 3 4 5 6 7 8 |
todos os projetos { repositórios { jcentro() mentor { url "http://files.couchbase.com/maven2/" } } } |
Agora, adicione as seguintes linhas ao nível superior dependências seção:
1 2 3 4 5 6 7 8 9 10 |
dependências { compilar fileTree(dir: 'libs', incluir: ['*.jar']) testCompile 'junit:junit:4.12' compilar 'com.android.support:appcompat-v7:23.1.0' compilar 'com.couchbase.lite:couchbase-lite-android:1.1.0' compilar 'com.couchbase.lite:couchbase-lite-java-listener:1.1.0' compilar 'com.couchbase.lite:couchbase-lite-java-javascript:1.1.0' compilar 'com.facebook.react:react-native:0.13.0' } |
Na barra de ferramentas do Android Studio, clique em Sync Project with Gradle Files (Sincronizar projeto com arquivos Gradle).
Configuração do Couchbase Lite e do Listener
Aberto AndroidManifest.xml localizado em app/src/main e adicione as permissões:
1 2 3 |
A atividade do React Native para Android
Você precisa adicionar algum código nativo para iniciar o tempo de execução do React Native e fazer com que ele renderize algo. Substitua o conteúdo de MainActivity.java com o seguinte e explicaremos o que está acontecendo a seguir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
público classe Atividade principal se estende Atividade implementa PadrãoHardwareBackBtnHandler { privado ReactRootView mReactRootView; privado ReactInstanceManager mReactInstanceManager; privado final Cordas TAG = "TodoLite"; privado estático final int DEFAULT_LISTEN_PORT = 5984; privado int listenPort; privado Credenciais allowedCredentials; @Substituir protegida vazio onCreate(Pacote savedInstanceState) { super.onCreate(savedInstanceState); Registro.d(TAG, "método onCreate chamado"); // 1 mReactRootView = novo ReactRootView(este); mReactInstanceManager = ReactInstanceManager.construtor() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModuleName("index.android") .addPackage(novo MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMIDO) .construir(); mReactRootView.startReactApplication(mReactInstanceManager, "TodoLite-ReactNative-Android", nulo); setContentView(mReactRootView); initCBLite(); } privado vazio initCBLite() { tentar { // 2 allowedCredentials = novo Credenciais("", ""); // 3 Ver.setCompiler(novo Compilador JavaScriptView()); // 4 AndroidContext contexto = novo AndroidContext(este); Gerente.enableLogging(Registro.TAG, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_SYNC, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_QUERY, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_VIEW, Registro.VERBOSE); Gerente.enableLogging(Registro.RASTREADOR DE ALTERAÇÕES DE TAGS, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_BLOB_STORE, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_DATABASE, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_LISTENER, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_MULTI_STREAM_WRITER, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_REMOTE_REQUEST, Registro.VERBOSE); Gerente.enableLogging(Registro.TAG_ROUTER, Registro.VERBOSE); Gerente gerente = novo Gerente(contexto, Gerente.DEFAULT_OPTIONS); // 5 listenPort = startCBLListener(DEFAULT_LISTEN_PORT, gerente, allowedCredentials); Registro.i(TAG, "initCBLite() completed successfully with: " + Cordas.formato( "http://%s:%s@localhost:%d/", allowedCredentials.getLogin(), allowedCredentials.getPassword(), listenPort)); } captura (final Exceção e) { e.printStackTrace(); } } privado int startCBLListener(int listenPort, Gerente gerente, Credenciais allowedCredentials) { LiteListener ouvinte = novo LiteListener(gerente, listenPort, allowedCredentials); int boundPort = ouvinte.getListenPort(); Tópico linha = novo Tópico(ouvinte); linha.iniciar(); retorno boundPort; } @Substituir protegida vazio onPause() { super.onPause(); se (mReactInstanceManager != nulo) { mReactInstanceManager.onPause(); } } @Substituir protegida vazio onResume() { super.onResume(); se (mReactInstanceManager != nulo) { mReactInstanceManager.onResume(este); } } @Substituir público vazio onBackPressed() { se (mReactInstanceManager != nulo) { mReactInstanceManager.onBackPressed(); } mais { super.onBackPressed(); } } @Substituir público booleano onKeyUp(int keyCode, KeyEvent evento) { se (keyCode == KeyEvent.KEYCODE_MENU &lificador;&lificador; mReactInstanceManager != nulo) { mReactInstanceManager.showDevOptionsDialog(); retorno verdadeiro; } retorno super.onKeyUp(keyCode, evento); } @Substituir público vazio invokeDefaultOnBackPressed() { super.onBackPressed(); } } |
Algumas coisas estão acontecendo aqui:
- Você cria uma atividade que cria um
ReactRootView
inicia um aplicativo React dentro dele e o define como a exibição de conteúdo principal. Em seguida, você está chamando a funçãoinitCBLite
que faz algumas coisas. - Aqui você define um nome e uma senha vazios a serem usados pelo Listener. Isso significa que, em teoria, qualquer pessoa poderia acessar seu banco de dados. Isso é aceitável para este tutorial, mas na produção você substituiria a linha por
novas Credenciais()
. - Conecte o componente para compilar as visualizações JavaScript. Ainda não usaremos as visualizações do Couchbase neste tutorial, mas elas podem ser úteis.
- Instanciar o
Gerente
e ativar o registro. - Inicie o Couchbase Listener informando a porta de escuta, a instância do gerenciador e as credenciais seguras.
Isso é tudo para a parte do Android, agora você pode voltar sua atenção para o JavaScript!
Terra do JavaScript
Na pasta raiz de seu projeto, execute:
1 2 3 |
$ npm inicial $ npm instalar --salvar reagir-nativo $ enrolar -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig |
Isso cria um módulo de nó para seu aplicativo e adiciona a dependência npm react-native. Agora, abra o módulo package.json e adicione esta linha dentro do arquivo roteiros
campo:
1 |
"start": "node_modules/react-native/packager/packager.sh" |
Olá mundo
Copie e cole o código a seguir em um novo arquivo index.android.js em sua pasta raiz:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
/** * Exemplo de aplicativo React Native * https://github.com/facebook/react-native */ 'use strict'; var Reagir = exigir('react-native'); var Início = exigir('./app/componentes/Home'); var { Registro de aplicativos, Folha de estilo, Texto, Ver, Barra de ferramentasAndroid } = Reagir; var estilos = Folha de estilo.criar({ contêiner: { flexível: 1, cor de fundo: '#111111' }, barra de ferramentas: { cor de fundo: '#e9eaed', altura: 56, } }); var TodoLite = Reagir.createClass({ renderizar: função() { retorno ( ); } }); Registro de aplicativos.registrarComponente('TodoLite-ReactNative-Android', () => TodoLite); |
Construir e executar!
Para executar seu aplicativo, primeiro você precisa iniciar o servidor de desenvolvimento. Para fazer isso, basta executar o seguinte comando em sua pasta raiz:
1 |
npm iniciar |
OBSERVAÇÃO: No momento da redação deste texto, talvez seja necessário executar brew update && brew reinstall watchman
para atualizar o watchman se você receber o erro Erro ao construir o DepdendencyGraph: TypeError: Não é possível ler a propriedade 'root' de null
.
Agora, crie e execute seu aplicativo Android em uma nova guia do Terminal:
1 |
./Gradlew installDebug |
Abra-o no simulador do Android e você verá o seguinte:
Parabéns por ter colocado o ambiente de desenvolvimento em funcionamento! O React Native inclui excelentes recursos, como o live reload, que facilitam muito a iteração na interface do usuário do aplicativo, mas primeiro você deve definir os modelos e métodos para persistir os documentos no banco de dados do Couchbase Lite.
Um aplicativo Todo
Uma API simples
Criar um novo arquivo app/utils/api.js e adicione o seguinte:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
var API = { // 1 localDatabaseUrl: 'http://localhost:5984', // 2 remoteDatabaseUrl: 'http://localhost:4984', // 3 saveTodo(título){ retorno buscar(este.localDatabaseUrl + '/todos', { método: 'post', cabeçalhos: { 'Content-Type': 'application/json' }, corpo: JSON.stringify({ tipo: 'lista', título: título }) }).então((res) => res.json()); }, // 4 getTodos(){ retorno buscar(este.localDatabaseUrl + '/todos/_all_docs?include_docs=true').então((resposta) => { se (resposta.status !== 200) { retorno buscar(este.localDatabaseUrl + '/todos', { método: 'colocar', cabeçalhos: { 'Aceitar': 'application/json', 'Content-Type': 'application/json' }, corpo: JSON.stringify({ok: verdadeiro}) }).então((res) => res.json()); } retorno resposta.json(); }) }, // 5 startSync(){ retorno buscar(este.localDatabaseUrl + '/_replicate', { método: 'post', cabeçalhos: { 'Content-Type': 'application/json' }, corpo: JSON.stringify({ fonte: 'todos', alvo: este.remoteDatabaseUrl + '/todos', contínuo: verdadeiro }) }).então((res) => res.json()); } }; módulo.exportações = API; |
Aqui está o que você está fazendo:
- Você declara o ponto de extremidade no qual o Couchbase Listener está sendo executado.
- Nesse caso, o banco de dados remoto é o Sync Gateway. Ele seria substituído por sua instância de produção do Sync Gateway.
- O método para manter um documento de tarefa.
- Aqui, você está obtendo todos os documentos do Couchbase Lite.
- Inicie uma replicação push do banco de dados do Couchbase Lite para o Sync Gateway. Também pode haver uma replicação pull.
Com uma API básica implementada, agora você pode voltar sua atenção para a criação da interface do usuário.
Criação da interface do usuário
Crie um novo arquivo em app/componentes/Home.js com o seguinte:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
var Reagir = exigir('react-native'); var API = exigir('./../utils/api'); var { Texto, Ver, Folha de estilo, ScrollView, TextInput, TouchableOpacity } = Reagir; var estilos = Folha de estilo.criar({ contêiner: { flexível: 1 }, buttonText: { fontSize: 18, cor: "branco, alignSelf: "centro }, rowContainer: { acolchoamento: 10 }, rowTitle: { cor: '#48BBEC', fontSize: 16 }, rowContent: { fontSize: 19 }, mainContainer: { flexível: 1, acolchoamento: 30, marginTop: 65, flexDireção: "coluna, justifyContent: "centro, cor de fundo: '#48BBEC' }, searchInput: { altura: 50, acolchoamento: 4, marginRight: 5, fontSize: 23, largura da borda: 1, borderColor: "branco, borderRadius: 8, cor: "branco, margem: 5 }, buttonText: { fontSize: 18, cor: '#111', alignSelf: "centro }, botão: { altura: 45, flexDireção: "linha, cor de fundo: "branco, borderColor: "branco, largura da borda: 1, borderRadius: 8, marginBottom: 10, marginTop: 10, alignSelf: "esticar, justifyContent: "centro }, }); classe Início se estende Reagir.Componente { construtor(adereços) { super(adereços); este.estado = { novoTodo: '', todos: [] }; } componentWillMount() { API.getTodos() .então((res) => { var todos = res.linhas.mapa(função (fila) { retorno fila.doc; }); este.setState({ todos: todos }); }); } handleTodoChange(evento) { este.setState({ novoTodo: evento.nativeEvent.texto }); } handleSave() { API.saveTodo(este.estado.novoTodo) .então((res) => { API.getTodos() .então((res) => { var todos = res.linhas.mapa(função (fila) { retorno fila.doc; }); este.refs.inputText.valor = ''; este.setState({ todos: todos, novoTodo: '' }); }); }); } handleSync() { API.startSync() .então(função(res) { console.registro(res); }); } renderizar() { var listas = este.estado.todos.mapa((item, índice) => { retorno ( {item.título} ); }); retorno ( Salvar Sincronização {listas} ); } } Início.propTypes = { listas: Reagir.PropTypes.matriz.isRequired }; módulo.exportações = Início; |
Não se deixe intimidar pelo tamanho desse trecho de código. Tudo o que estamos fazendo aqui é declarar estilos e usar alguns componentes de IU do React Native incorporados para exibir uma entrada de texto, botões e rótulos de texto. Você pode encontrar a lista de componentes de IU incorporados aqui.
Atualização do componente raiz
A etapa final para que você possa ver seu excelente trabalho em ação é atualizar index.android.js para carregar o Início componente. Abaixo do exigir
para importar react-nativo
Adicione o seguinte:
1 |
var Início = exigir('./app/componentes/Home'); |
Em seguida, substitua o valor de retorno do renderizar
método com . Use o
⌘ + m
no Genymotion para recarregar o JavaScript e você verá uma tela azul brilhante. Essa é uma boa notícia!
Replicações com o Couchbase Sync Gateway
Faça o download do Sync Gateway no link abaixo e descompacte o arquivo:
http://www.couchbase.com/nosql-databases/downloads
Em um novo arquivo chamado sync-gateway-config.json, cole o seguinte:
1 2 3 4 5 6 7 8 9 |
{ "log": ["*"], "bancos de dados": { "todos": { "servidor": "walrus:", "usuários": { "CONVIDADO": { "desativado": falso, "admin_channels": ["*"] } } } } } |
E execute o Sync Gateway com esse arquivo de configuração:
1 |
~/Downloads/couchbase-sincronização-portal/caixa/portais de sincronização /caminho/para/projeto/sincronização-portal-configuração.json |
Para tornar o ponto de extremidade do Sync Gateway acessível dentro do emulador de VM do Android, você precisa ativar uma porta do host para a VM. No Terminal, execute o seguinte:
1 |
adb reverso tcp:4984 tcp:4984 |
Abra a interface de usuário do administrador para monitorar os documentos que foram salvos no Sync Gateway:
http://localhost:4985/_admin/
Tente adicionar mais documentos de tarefas e observe como eles são enviados automaticamente para o Sync Gateway.
Para onde ir a partir de agora
Parabéns! Você criou seu primeiro aplicativo React Native Android + Couchbase Lite. Agora você está pronto para adicionar mais componentes, como os seguintes:
- Visualizações do Couchbase Lite para escrever consultas personalizadas
- Autenticação do usuário em uma replicação
- Implementação contínua do arquivo de configuração do Sync Gateway e outros componentes
Fique atento a um tutorial sobre a depuração de seu aplicativo React Native Android + Couchbase Lite usando Charles e Genymotion.
Sinta-se à vontade para compartilhar seus comentários, descobertas ou fazer perguntas nos comentários abaixo ou nos fóruns. Falamos com você em breve!
*Abra o AndroidManifest.xml localizado em app/src/main e adicione as permissões
A linha acima indica as permissões, mas nenhuma foi encontrada na caixa fornecida abaixo dela.