Kotlin

      +

      Description — Couchbase Lite for Android — Kotlin support
      Related Content — Databases | Documents | Indexing |

      Introduction

      Couchbase Lite Android 3.1.6 introduces full idiomatic support for Kotlin apps, out-of-the-box.

      Kotlin developers can now build apps using common Kotlin Patterns, that integrate seamlessly with Couchbase Lite for Android and have full feature parity with the Java API; including some convenient Kotlin Extensions to get you started.

      Key features include:

      • Nullability annotations

      • Named parameters

      • Kotlin Flows, for asynchronous event notifications

      Java support and functionality continues for Android.

      Kotlin Extensions

      In addition to having full co-compatible access to the existing Java API, Kotlin developers can also access a number of Kotlin Extensions.

      The Kotlin Extensions package includes:

      • Configuration Factories for the configuration of important Couchbase Lite objects such as Databases, Replicators and Listeners.

      • Change Flows that monitor key Couchbase Lite objects fpr change using Kotlin features such as, Co-routines and Flows.

      See: Kotlin Extensions for extension API docs

      Configuration Factories

      Couchbase Lite provides a set of ConfigurationFactories and CommonConfigurationFactories, these allow use of named parameters to specify property settings.

      This makes it simple to create variant configurations, by simply overriding named parameters:

      Example of overriding configuration
      val listener8080 = URLEndpointListenerConfigurationFactory.newConfig(
          networkInterface = "en0",
          port = 8080
      )
      val listener8081 = listener8080.newConfig(port = 8081)

      Database

      Use DatabaseConfigurationFactory to create a DatabaseConfiguration object, overriding the receiver’s values with the passed parameters.

      • In Use

      • Definition

      database = Database(
          "getting-started",
          DatabaseConfigurationFactory.newConfig()
      )
      val DatabaseConfigurationFactory: DatabaseConfiguration? = null
      
      fun DatabaseConfiguration?.create(
          databasePath: String? = null,
          encryptionKey: EncryptionKey? = null
      )

      Replication

      Use ReplicatorConfigurationFactory to create a ReplicatorConfiguration object, overriding the receiver’s values with the passed parameters.

      • In Use

      • Definition

      val replicator =
          Replicator(
              ReplicatorConfigurationFactory.newConfig(
                  collections = mapOf(db.collections to null),
                  target = URLEndpoint(URI("ws://localhost:4984/getting-started-db")),
                  type = ReplicatorType.PUSH_AND_PULL,
                  authenticator = BasicAuthenticator("sync-gateway", "password".toCharArray())
              )
          )
      val ReplicatorConfigurationFactory: ReplicatorConfiguration? = null
      
      fun ReplicatorConfiguration?.create(
          database: Database? = null,
          target: Endpoint? = null,
          type: ReplicatorType? = null,
          continuous: Boolean? = null,
          authenticator: Authenticator? = null,
          headers: Map<String, String>? = null,
          pinnedServerCertificate: ByteArray? = null,
          channels: List<String>? = null,
          documentIDs: List<String>? = null,
          pushFilter: ReplicationFilter? = null,
          pullFilter: ReplicationFilter? = null,
          conflictResolver: ConflictResolver? = null,
          maxAttempts: Int? = null,
          maxAttemptWaitTime: Int? = null,
          heartbeat: Int? = null,
          enableAutoPurge: Boolean? = null,
          acceptOnlySelfSignedServerCertificate: Boolean? = null
      )
      
      val MessageEndpointListenerConfigurationFactory: MessageEndpointListenerConfiguration? = null
      
      fun MessageEndpointListenerConfiguration?.create(
          database: Database? = null,
          protocolType: ProtocolType? = null
      )

      Use FullTextIndexConfigurationFactory to create a FullTextIndexConfiguration object, overriding the receiver’s values with the passed parameters.

      • In Use

      • Definition

      collection.createIndex(
          "overviewFTSIndex",
          FullTextIndexConfigurationFactory.newConfig("overview"))
      val FullTextIndexConfigurationFactory: FullTextIndexConfiguration? = null
      
      fun FullTextIndexConfiguration?.create(expression: String? = null)

      Indexing

      Use ValueIndexConfigurationFactory to create a ValueIndexConfiguration object, overriding the receiver’s values with the passed parameters.

      • In Use

      • Definition

      collection.createIndex(
          "TypeNameIndex",
          ValueIndexConfigurationFactory.newConfig("type", "name")
      )
      val ValueIndexConfigurationFactory: ValueIndexConfiguration? = null
      
      fun ValueIndexConfiguration?.create(vararg expressions: String = emptyArray())

      Logs

      Use LogFileConfigurationFactory to create a LogFileConfiguration object, overriding the receiver’s values with the passed parameters.

      • In Use

      • Definition

      Database.log.file.let {
          it.config = LogFileConfigurationFactory.newConfig(
              context.cacheDir.absolutePath, (1)
              maxSize = 10240, (2)
              maxRotateCount = 5, (3)
              usePlainText = false
          ) (4)
          it.level = LogLevel.INFO (5)
      
      }
      val LogFileConfigurationFactory: LogFileConfiguration? = null
      
      .LogFileConfiguration.create()
      
      fun LogFileConfiguration?.create(
          directory: String? = null,
          maxSize: Long? = null,
          maxRotateCount: Int? = null,
          usePlainText: Boolean? = null
      )

      Flows

      These wrappers use Flowables to monitor for changes.

      Database Change Flow

      Use the databaseChangeFlow(Database,Executor) to monitor database change events.

      • In Use

      • Definition

      val updatedDocs = db.databaseChangeFlow()
          .map { it.documentIDs }
          .asLiveData()
      @ExperimentalCoroutinesApi
      fun Database.databaseChangeFlow(executor: Executor? = null)

      Document Change Flow

      Use documentChangeFlow(Database,String,Executor) to monitor changes to a document.

      • In Use

      • Definition

      val docModDate = db.documentChangeFlow("1001", null)
          .map { it.collection.getDocument(it.documentID)?.getString("lastModified") }
          .asLiveData()
      @ExperimentalCoroutinesApi
      
      fun Database.documentChangeFlow(documentId: String, executor: Executor? = null)

      Replicator Change Flow

      Use replicatorChangeFlow(Replicator,Executor) to monitor replicator changes.

      • In Use

      • Definition

      val replState = repl.replicatorChangesFlow()
          .map { it.status.activityLevel }
          .asLiveData()
      @ExperimentalCoroutinesApi
      fun Replicator.replicatorChangesFlow(executor: Executor? = null)

      Document Replicator Change Flow

      Use documentReplicationFlow(Replicator,Executor) to monitor document changes during replication.

      • In Use

      • Definition

      val replicatedDocs = repl.documentReplicationFlow(testSerialExecutor)
          .map { update -> update.documents }
          .onEach { listView.setUpdated(it) }
          .collect()
      @ExperimentalCoroutinesApi
      fun Replicator.documentReplicationFlow(executor: Executor? = null)

      Query Change Flow

      Use queryChangeFlow(Query,Executor) to monitor document changes during replication.

      • In Use

      • Definition

      fun watchQuery(query: Query): LiveData<List<Result>> {
          return query.queryChangeFlow()
              .mapNotNull { change ->
                  val err = change.error
                  if (err != null) {
                      throw err
                  }
                  change.results?.allResults()
              }
              .asLiveData()
      }
      @ExperimentalCoroutinesApi
      fun Query.queryChangeFlow(executor: Executor? = null)