Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs

Início rápido com LiveData - Java SDK

Esta página contém instruções para integrar rapidamente o Realm a um exemplo de aplicação Android que usa LiveData. Este aplicação de exemplo permite que um usuário incremente um contador usando um botão.

Este guia de início rápido usa o Sync para sincronizar alterações de dados entre clientes. Antes de começar, verifique se tem:

Observação

Usando LiveData sem Sincronizar

Para usar esse início rápido sem o Sync, desative os recursos de sincronização no SDK. Você pode fazer isso removendo as seguintes linhas do arquivo build.gradle no nível do aplicativo:

realm {
syncEnabled = true
}

Depois de remover as linhas, sincronize novamente a configuração do Gradle para recarregar o Java SDK em um estado somente offline. Remova as linhas relacionadas à importação e ao uso da Configuração de sincronização, do login do usuário e do valor da partição do arquivo CounterModel para usar o Java SDK sem sincronização.

Para começar, copie o repositório de exemplo em seu ambiente local.

Já reunimos um aplicativo Android que tem a maior parte do código de que você precisa. Você pode clonar o repositório de aplicação do cliente diretamente do Github:

git clone https://github.com/mongodb-university/realm-android-livedata.git

O repositório contém duas ramificações: final e start. A ramificação final é uma versão finalizada do aplicativo, pois ela deve procurar depois que você concluir este tutorial. Para aprender este tutorial, confira a ramificação start :

git checkout start

Agora que você clonou o repositório, precisa adicionar as dependências necessárias para executar o Java SDK e o Android LiveData. Comece adicionando a dependência do Java SDK ao bloco buildscript.dependencies do seu arquivo build.gradle no nível do projeto:

buildscript {
ext.kotlin_version = "1.4.10"
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "io.realm:realm-gradle-plugin:10.2.0"
}
}

Você também terá que adicionar a dependência Android LiveData ao bloco dependencies do seu arquivo build.gradle de nível de aplicativo:

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

Em seguida, habilite a Sincronização no SDK criando o seguinte bloco de nível superior no arquivo build.gradle do nível do aplicativo:

realm {
syncEnabled = true
}

Em seguida, habilite o DataBinding criando o seguinte bloco no bloco android do seu arquivo de nível de aplicativo build.gradle :

android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.mongodb.realm.livedataquickstart"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
dataBinding true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

Por fim, clique no botão "Sincronizar" ou selecione Build > Rebuild Project no menu do aplicativo para reconfigurar a configuração do Gradle com essas alterações e obter as dependências.

Com todas as dependências em vigor, é hora de criar uma interface compatível com LiveData para nossos Objeto de Realm. Para fazer isso, teremos que lidar com alguns eventos:

  • O método onActive() permite que um observador assine alterações no objeto Realm subjacente adicionando um ouvinte de alterações.

    override fun onActive() {
    super.onActive()
    val obj = value
    if (obj != null && RealmObject.isValid(obj)) {
    RealmObject.addChangeListener(obj, listener)
    }
    }
  • O método onInactive() permite que um observador cancele a assinatura de alterações no Objeto de Realm subjacente removendo o ouvinte de alterações.

    override fun onInactive() {
    super.onInactive()
    val obj = value
    if (obj != null && RealmObject.isValid(obj)) {
    RealmObject.removeChangeListener(obj, listener)
    }
    }
  • Quando ocorre uma alteração, o listener membro usa o setValue() método da LiveData classe pai para passar o valor do objeto Realm para a UI, a menos que o objeto tenha sido excluído, caso em que o ouvinte de alterações passa um valor de em null vez de passar uma referência para um objeto inválido e excluído.

    private val listener =
    RealmObjectChangeListener<T> { obj, objectChangeSet ->
    if (!objectChangeSet!!.isDeleted) {
    setValue(obj)
    } else { // Because invalidated objects are unsafe to set in LiveData, pass null instead.
    setValue(null)
    }
    }

Dica

Uso de LiveData com RealmResults

Este exemplo utiliza somente LiveData para exibir RealmObjects na interface do usuário. Para uma implementação de amostra RealmResults exibindo, consulte LiveRealmResults.

Este aplicativo armazena toda a sua lógica e dados principais dentro de um ViewModel chamado CounterModel. Quando o aplicativo é executado, ele cria uma instância do CounterModel que é utilizada até o aplicativo ser fechado. Essa instância contém o LiveData exibido na interface do usuário do aplicativo. Para criar uma instância do LiveData, precisamos acessar um objeto Counter armazenado em um domínio e passá-lo para o construtor LiveRealmObject . Para fazer isso:

  1. Conecte-se ao seu aplicativo com seu ID do aplicativo.

  2. Autenticar um usuário.

  3. Conecte-se a um Realm específico usando a sincronização.

  4. query o Realm em busca de um Counter, inserindo um novo Counter se um ainda não tiver sido criado nesse Realm.

  5. Instancie um LiveRealmObject utilizando a instância do Counter e armazene-o no membro counter de CounterModel.

O seguinte trecho de código implementa esse comportamento:

init {
val appID = "YOUR APP ID HERE" // TODO: replace this with your App ID
// 1. connect to the MongoDB Realm app backend
val app = App(
AppConfiguration.Builder(appID)
.build()
)
// 2. authenticate a user
app.loginAsync(Credentials.anonymous()) {
if(it.isSuccess) {
Log.v("QUICKSTART", "Successfully logged in anonymously.")
// 3. connect to a realm with Realm Sync
val user: User? = app.currentUser()
val partitionValue = "example partition"
val config = SyncConfiguration.Builder(user!!, partitionValue)
// because this application only reads/writes small amounts of data, it's OK to read/write from the UI thread
.allowWritesOnUiThread(true)
.allowQueriesOnUiThread(true)
.build()
// open the realm
realm = Realm.getInstance(config)
// 4. Query the realm for a Counter, creating a new Counter if one doesn't already exist
// access all counters stored in this realm
val counterQuery = realm!!.where<Counter>()
val counters = counterQuery.findAll()
// if we haven't created the one counter for this app before (as on first launch), create it now
if (counters.size == 0) {
realm?.executeTransaction { transactionRealm ->
val counter = Counter()
transactionRealm.insert(counter)
}
}
// 5. Instantiate a LiveRealmObject using the Counter and store it in a member variable
// the counters query is life, so we can just grab the 0th index to get a guaranteed counter
this._counter.postValue(counters[0]!!)
} else {
Log.e("QUICKSTART", "Failed to log in anonymously. Error: ${it.error.message}")
}
}
}

Importante

Não leia ou escreva na thread da interface do usuário

As leituras e gravações de reconhecimento de data center são computacionalmente caras, portanto, o SDK desativa as leituras e gravações por padrão no thread da UI. Para simplificar, este exemplo permite leituras e gravações de thread da UI com os métodos do construtor de configuração allowWritesOnUiThread() e allowQueriesOnUiThread() . Em aplicativos de produção, você deve quase sempre adiar leituras e gravações para um thread em segundo plano usando métodos assíncronos.

Para exibir os dados armazenados no na CounterModel interface CounterModel do usuário do aplicação , precisaremos acessar o singleton do utilizando o método viewModels() quando o aplicação criar CounterFragment o. Depois de instanciar o modelo, podemos usar a biblioteca Android Data Binding para exibir os dados do modelo em elementos da UI.

Para acessar o singleton CounterModel quando o aplicativo cria CounterFragment, coloque o seguinte código no método onCreateView() de CounterFragment:

val model: CounterModel by viewModels()

Em seguida, configure os ganchos de vinculação de dados na interface do usuário para o fragmento do contador:

<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="counterModel"
type="com.mongodb.realm.livedataquickstart.model.CounterModel"
/>
</data>
<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=".CounterFragment">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{counterModel.counter.value.get().toString()}"
android:textSize="58pt"
app:layout_constraintBottom_toTopOf="@id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textview" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Por fim, conecte o modelo à associação para que a UI possa exibir o contador e iterar o contador ao pressionar o botão com o seguinte código no método onCreateView() de CounterFragment :

val binding = CounterFragmentBinding.inflate(inflater, container, false).apply {
lifecycleOwner = viewLifecycleOwner
counterModel = model
}
binding.root.button.setOnClickListener {
Log.v("QUICKSTART", "Clicked increment button. Current value: ${model.counter.value?.value?.get()}")
model.incrementCounter()
}
return binding.root

Agora você deve ser capaz de executar o aplicativo de amostra. Você deve ver uma interface parecida com esta:

O aplicativo LiveData QuickStart Contador.

Clicar no botão "ADD" deve adicionar um ao valor do seu contador. Com a sincronização, você pode ver seus registros de aplicações para ver eventos de incremento individuais. O Android LiveData reconhece o ciclo de vida, portanto, girar a tela ou liberar o estado do aplicativo limpando a RAM do dispositivo não deve afetar o estado do aplicativo, que deve ser retomado sem problemas e assinado novamente automaticamente os eventos na retomada usando o estado armazenado no modelo único e a instância LiveData encapsulada.

  • Use as classes LiveRealmObject e LiveRealmResults como modelo para encapsular dados ativos do Realm no Android LiveData.

  • Use um ViewModel para separar os dados subjacentes dos elementos da interface do usuário que exibem esses dados.

  • O DataBinding permite que você declare relacionamentos entre os dados do modelo e os elementos da interface do usuário sem definir explicitamente os valores em uma atividade ou fragmento.

Você encontrou este guia de início rápido útil? Informe-nos com o formulário de feedback no lado direito da página!

Próximo

Bem-vindo aos Docs do Atlas Device SDK

Nesta página