1. 程式人生 > >如何使用GraphQL Client: Apollo Android

如何使用GraphQL Client: Apollo Android

# 如何使用GraphQL Client: Apollo Android 一個Android app, 如何使用GraphQL. 本文以最流行的Apollo Android為例來說明. ## 新增依賴 首先, 新增依賴: https://www.apollographql.com/docs/android/essentials/get-started-kotlin/ 注意在android block裡這兩個東東都要加上: ``` compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } ``` ## 下載Schema 然後, 下載schema. 可以跑一個introspection query來獲取. Apollo的Gradle外掛貼心地提供了這個功能, 用`downloadApolloSchema`這個task就可以. 只需要提供server的endpoint和儲存schema.json檔案的位置: ``` ./gradlew downloadApolloSchema \ --endpoint="https://your.domain/graphql/endpoint" \ --schema="src/main/graphql/com/example/schema.json" ``` 如果是需要認證的endpoint: ``` ./gradlew downloadApolloSchema \ --endpoint="https://your.domain/graphql/endpoint" \ --schema="app/src/main/graphql/com/example" \ --header="Authorization: Bearer $TOKEN" ``` 這裡我曾經有過一個疑問, 我這個TOKEN屬於哪個使用者的要緊嗎? -> 不要緊. 注意: 此時用的Token只是為了獲取schema, 實際請求的時候還是要帶具體當時的token. ## 新增.graphql檔案, build生成程式碼 找Playground測試, 比如GitHub GraphQL API可以用Explorer測試: https://developer.github.com/v4/explorer/ 然後把這個`.graphql`檔案寫在schema檔案旁邊. 比如: `CurrentUser.graphql`中: ``` query CurrentUser { viewer { login avatarUrl name } } ``` Build, 生成程式碼. 生成程式碼在生成檔案的路徑. 比如`CurrentUser.graphql`裡面是一個query, 就生成了`CurrentUserQuery`檔案. ## 進行請求呼叫 (協程版本) 採用協程版本的程式碼, 在ViewModel的scope裡面: ``` viewModelScope.launch { val response = try { apolloClient.query(CurrentUserQuery()).toDeferred().await() } catch (e: ApolloException) { // handle protocol errors return@launch } val viewer = response.data?.viewer if (viewer == null || response.hasErrors()) { // handle application errors return@launch } _user.postValue(viewer) println("Launch site: ${viewer.login}") } ``` 其中`toDeferred()`方法將結果轉換為`Deferred`, 是`Job`的一個子類, `await()`方法返回協程的結果. ### Apollo Client Android的協程支援 添加了這個依賴之後: ``` implementation("com.apollographql.apollo:apollo-coroutines-support:2.2.3") ``` 會有一個輔助類, 裡面目前是5個擴充套件方法: * Converts an [ApolloCall] to an [Flow] * Converts an [ApolloQueryWatcher] to an [Flow]. * Converts an [ApolloCall] to an [Deferred]. * Converts an [ApolloSubscriptionCall] to an [Flow]. * Converts an [ApolloPrefetch] to [Job]. ## 認證請求 關於認證的請求: https://www.apollographql.com/docs/android/tutorial/10-authenticate-your-queries/ 同樣也是加interceptor來解決: ``` return ApolloClient.builder() .serverUrl("https://api.github.com/graphql") .okHttpClient( OkHttpClient.Builder() .addInterceptor(authInterceptor) .build() ) .build() ``` 其中authInterceptor和用Retrofit時候的一樣. ``` class AuthInterceptor constructor(private val preferencesUtils: PreferencesUtils) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val userToken = preferencesUtils.userToken val newBuilder = chain.request().newBuilder() if (userToken != null && userToken.isNotEmpty()) { newBuilder.addHeader("Authorization", "token $userToken") } newBuilder.addHeader("Accept", "application/vnd.github.v3+json") val request = newBuilder.build() return chain.proceed(request) } } ``` ## 參考 * [Apollo Android官網文件](https://www.apollographql.com/docs/an