API Reference / API Methods / Install the Kotlin API Client

Install the Kotlin API Client

The Kotlin client is compatible with Kotlin 1.3.30 and higher.

Install the Kotlin client by adding the following dependency to your gradle.build file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
repositories {
    mavenCentral()
}

dependencies {
    implementation "com.algolia:algoliasearch-client-kotlin:$kotlin_client_version"
    // for Gradle version < 6.0, use the following instead
    implementation "com.algolia:algoliasearch-client-kotlin-jvm:$kotlin_client_version"
    // Choose one of the following HTTP clients
    implementation "io.ktor:ktor-client-apache:$ktor_version"
    implementation "io.ktor:ktor-client-okhttp:$ktor_version"
    implementation "io.ktor:ktor-client-android:$ktor_version"
    implementation "io.ktor:ktor-client-cio:$ktor_version"
    implementation "io.ktor:ktor-client-jetty:$ktor_version"
}

Read more about ktor HTTP client here.

Supported platforms

The Kotlin client is compatible with the JVM. It is recommended for the following use cases:

  • Frontend Android projects using Kotlin
  • Backend JVM projects using Kotlin

Philosophy

Stack

This client provides a Kotlin implentation for using AlgoliaSearch. It is built using the official Kotlin stack:

Integrated documentation

The Kotlin client integrates the actual Algolia documentation in each source file: Request parameters, response fields, methods and concepts; all are documented and link to the corresponding url of the Algolia doc website.

Type safety

Response and parameters objects are typed to provide extensive compile-time safety coverage.

Example for creating a Client instance without mixing the application ID and the API key.

1
2
3
4
val appID = ApplicationID("YourApplicationID")
val apiKey = APIKey("YourAdminAPIKey")

val client = ClientSearch(appID, apiKey)

Example for attributes:

1
2
3
val color = Attribute("color")
val category = Attribute("category")
val query = Query(attributesToRetrieve = listOf(color, category))

Sealed classes are used to represent enumerated types. It allows to quickly discover possible values for each type thanks to IDE autocomplete support. Each enumerated type has an Other case to pass a custom value.

1
2
3
4
5
val query = Query()

query.sortFacetsBy = SortFacetsBy.Count
// query.sortFacetsBy = SortFacetsBy.Alpha
// query.sortFacetsBy = SortFacetsBy.Other("custom value")

DSL

Extensive DSL coverage is provided to encourage a declarative style which retains the benefits of compile time safety while being more lightweight.

Example for query parameters:

1
2
3
4
5
6
val query = query { 
   attributesToRetrieve { 
       +"color"
       +"category"
   }
}

Example for settings:

1
2
3
4
5
val settings = settings {
   attributesToSnippet {
       +"content"(10)
   }
}

Example for filters:

1
2
3
4
5
6
7
8
9
10
11
12
val query = query {
   filters {
       and {
           facet("color", "red")
           facet("category", "shirt")
       }
       orNumeric {
           range("price", 0 until 10)
           comparison("price", Equals, 15)
       }
   }
}

Json serialization

The Kotlin client relies on the kotlinx serialization library.

Search Response

Deserialize hits from a search response using the deserialize extension functions.

1
2
3
4
5
6
7
8
9
@Serializable
data class Contact(
    val firstname: String,
    val lastname: String
)

val response = index.search()

val contacts: List<Contact> = response.hits.deserialize(Contact.serializer())
GetObject

Deserialize data from a getObject call by passing a serializer as parameter.

1
2
3
4
5
6
7
8
9
10
@Serializable
data class Contact(
    val firstname: String,
    val lastname: String,
    override val objectID: ObjectID
) : Indexable

val objectID = ObjectID("myID1")

val contact: Contact = index.getObject(Contact.serializer(), objectID)
General

A JsonObject can be transformed at any moment using the library standard methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Serializable
data class Contact(
    val firstname: String,
    val lastname: String
)
val json: JsonObject = buildJsonObject {
    put("firstname", "Jimmie")
    put("lastname", "Barninger")
}

val contact: Contact = Json.decodeFromJsonElement(Contact.serializer(), json)

// Or configure your own Json instance:
val JsonNonStrict = Json {
    ignoreUnknownKeys = true
    isLenient = true
    allowSpecialFloatingPointValues = true
}
val contactNonStrict: Contact = JsonNonStrict.decodeFromJsonElement(Contact.serializer(), json)

Learn more about kotlinx serialization.

Exception handling

In case of success, an HTTP call returns the appropriate typed object.

1
val response: ResponseSearch = index.search()

However, an HTTP exception can occur. Handle it with a try / catch block.

1
2
3
4
5
6
7
8
try {
    val response = index.search()
} catch (exception: ResponseException) {
    when (exception.response.status) {
        HttpStatusCode.NotFound -> TODO()
        HttpStatusCode.BadRequest -> TODO()
    }
}

Other kinds of exceptions can occur. Handle them appropriately.

1
2
3
4
5
6
7
8
9
try {
    val response = index.search()
} catch (exception: ResponseException) {
    TODO()
} catch (exception: IOException) {
    TODO()
} catch (exception: Exception) {
    TODO()
}

Coroutines

All methods performing HTTP calls in the Kotlin client are suspending functions. This means these functions can only be called from a coroutine scope.

In the example below, a coroutine is launched in the main thread. The context is switched to a thread pool to perform the search HTTP call off the main thread. The response can be manipulated from the main thread.

1
2
3
4
5
6
7
8
9
10
class Searcher : CoroutineScope {

    override val coroutineContext = SupervisorJob()

    fun search() {
        launch(Dispatchers.Main) {
            val response = withContext(Dispatchers.Default) { index.search() }
        }
    }
}

The developer is responsible for implementing the asynchronous logic that matches their specific requirements. The Kotlin client doesn’t execute HTTP calls on any particular thread, it is up to the developer to define it explicitly using coroutines. Learn more about coroutines.

Waiting for operations

Waiting for an asynchronous server task is made available via a function literal with receiver.

Use the apply or run functions on your index or client.

1
2
3
4
5
6
index.apply {
    setSettings(Settings()).wait()
}
client.run {
    multipleBatchObjects(listOf<BatchOperationIndex>()).waitAll()
}

The wait functions are suspending, and should only be called from a coroutine.

Multithreading

The client is designed to be thread-safe. You can use SearchClient, AnalyticsClient, and InsightsClient in a multithreaded environment.

Did you find this page helpful?