Learn how to integrate Apito's GraphQL tools and database API with your Android applications using Apollo Android. This instant API builder provides powerful GraphQL endpoints and build API tool features optimized for mobile development.
Apito's GraphQL tools and database API offer seamless integration with Android applications through Apollo Android client. This instant API platform generates type-safe Kotlin/Java models from your GraphQL schema, ensuring excellent performance and developer experience on mobile devices.
Add the following dependencies to your app-level build.gradle
file:
dependencies {
implementation 'com.apollographql.apollo3:apollo-runtime:3.8.2'
implementation 'com.apollographql.apollo3:apollo-android-support:3.8.2'
// For coroutines support
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
}
Add the Apollo plugin to your app-level build.gradle
:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.apollographql.apollo3' version '3.8.2'
}
schema.graphqls
src/main/graphql/
directoryCreate an apollo
configuration block in your build.gradle
:
apollo {
service("apito") {
packageName.set("com.yourapp.graphql")
schemaFile.set(file("src/main/graphql/schema.graphqls"))
}
}
Create an Apollo client in your Application class or dependency injection module:
import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.network.okHttpClient
import okhttp3.Interceptor
import okhttp3.OkHttpClient
class ApitoGraphQLClient {
companion object {
private const val BASE_URL = "https://api.apito.io/secured/graphql"
private const val API_KEY = "your-api-key-here"
val apolloClient: ApolloClient by lazy {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor { chain ->
val request = chain.request().newBuilder()
.addHeader("X-API-KEY", API_KEY)
.addHeader("Content-Type", "application/json")
.build()
chain.proceed(request)
}
.build()
ApolloClient.Builder()
.serverUrl(BASE_URL)
.okHttpClient(okHttpClient)
.build()
}
}
}
Create GraphQL query files in src/main/graphql/
:
GetProducts.graphql:
query GetProducts($limit: Int, $offset: Int) {
products(limit: $limit, offset: $offset) {
id
title
description
price
image {
url
}
categories {
id
name
}
}
}
CreateProduct.graphql:
mutation CreateProduct($input: ProductInput!) {
createProduct(input: $input) {
id
title
description
price
createdAt
}
}
import com.apollographql.apollo3.exception.ApolloException
import kotlinx.coroutines.launch
import androidx.lifecycle.lifecycleScope
class ProductActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_product)
fetchProducts()
}
private fun fetchProducts() {
lifecycleScope.launch {
try {
val response = ApitoGraphQLClient.apolloClient
.query(GetProductsQuery(limit = 10, offset = 0))
.execute()
if (response.hasErrors()) {
// Handle GraphQL errors
response.errors?.forEach { error ->
Log.e("GraphQL", "Error: ${error.message}")
}
} else {
// Handle successful response
response.data?.products?.let { products ->
displayProducts(products)
}
}
} catch (e: ApolloException) {
Log.e("Apollo", "Network error: ${e.message}")
}
}
}
private fun displayProducts(products: List<GetProductsQuery.Product>) {
products.forEach { product ->
Log.d("Product", "Title: ${product.title}, Price: ${product.price}")
}
// Update your RecyclerView or UI components
}
}
private fun createProduct(title: String, description: String, price: Double) {
lifecycleScope.launch {
try {
val input = ProductInput(
title = title,
description = description,
price = price
)
val response = ApitoGraphQLClient.apolloClient
.mutation(CreateProductMutation(input))
.execute()
if (response.hasErrors()) {
// Handle errors
showError("Failed to create product")
} else {
// Handle success
response.data?.createProduct?.let { product ->
showSuccess("Product created with ID: ${product.id}")
}
}
} catch (e: ApolloException) {
showError("Network error: ${e.message}")
}
}
}
For better architecture, implement the Repository pattern:
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ProductRepository @Inject constructor(
private val apolloClient: ApolloClient
) {
suspend fun getProducts(limit: Int, offset: Int): Result<List<Product>> {
return try {
val response = apolloClient
.query(GetProductsQuery(limit, offset))
.execute()
if (response.hasErrors()) {
Result.failure(Exception("GraphQL errors: ${response.errors}"))
} else {
val products = response.data?.products?.map { it.toProduct() } ?: emptyList()
Result.success(products)
}
} catch (e: ApolloException) {
Result.failure(e)
}
}
suspend fun createProduct(productInput: ProductInput): Result<Product> {
return try {
val response = apolloClient
.mutation(CreateProductMutation(productInput))
.execute()
if (response.hasErrors()) {
Result.failure(Exception("GraphQL errors: ${response.errors}"))
} else {
response.data?.createProduct?.let { product ->
Result.success(product.toProduct())
} ?: Result.failure(Exception("No data received"))
}
} catch (e: ApolloException) {
Result.failure(e)
}
}
}
// Extension function to map GraphQL types to domain models
private fun GetProductsQuery.Product.toProduct(): Product {
return Product(
id = id,
title = title,
description = description,
price = price,
imageUrl = image?.url
)
}
Use with Android Architecture Components:
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class ProductViewModel @Inject constructor(
private val productRepository: ProductRepository
) : ViewModel() {
private val _products = MutableStateFlow<List<Product>>(emptyList())
val products: StateFlow<List<Product>> = _products
private val _loading = MutableStateFlow(false)
val loading: StateFlow<Boolean> = _loading
private val _error = MutableStateFlow<String?>(null)
val error: StateFlow<String?> = _error
fun loadProducts() {
viewModelScope.launch {
_loading.value = true
_error.value = null
productRepository.getProducts(limit = 20, offset = 0)
.onSuccess { products ->
_products.value = products
}
.onFailure { exception ->
_error.value = exception.message
}
_loading.value = false
}
}
fun createProduct(title: String, description: String, price: Double) {
viewModelScope.launch {
val input = ProductInput(title, description, price)
productRepository.createProduct(input)
.onSuccess {
loadProducts() // Refresh the list
}
.onFailure { exception ->
_error.value = exception.message
}
}
}
}
Implement comprehensive error handling:
sealed class GraphQLResult<T> {
data class Success<T>(val data: T) : GraphQLResult<T>()
data class Error<T>(val message: String, val errors: List<com.apollographql.apollo3.api.Error>? = null) : GraphQLResult<T>()
data class NetworkError<T>(val exception: ApolloException) : GraphQLResult<T>()
}
suspend fun <T> executeGraphQLQuery(
query: suspend () -> com.apollographql.apollo3.api.ApolloResponse<T>
): GraphQLResult<T> {
return try {
val response = query()
if (response.hasErrors()) {
GraphQLResult.Error(
message = "GraphQL errors occurred",
errors = response.errors
)
} else {
response.data?.let { data ->
GraphQLResult.Success(data)
} ?: GraphQLResult.Error("No data received")
}
} catch (e: ApolloException) {
GraphQLResult.NetworkError(e)
}
}
// Enable normalized caching
val apolloClient = ApolloClient.Builder()
.serverUrl(BASE_URL)
.normalizedCache(
MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024) // 10MB
)
.build()
Integrating Apito's GraphQL API with Android applications provides a robust, type-safe solution for mobile data management. This open source API builder offers excellent performance and developer experience for Android development.
The combination of Apito's open source CMS and Apollo Android ensures scalable, maintainable mobile applications with powerful GraphQL integration.