كيفية تكوين Apollo للعمل مع GraphQL في Android

لماذا مقال


في الآونة الأخيرة ، كنت بحاجة إلى تنفيذ العمل مع الواجهة الخلفية في GraphQL. لا يوجد الكثير من البرامج التعليمية لإعداد Android ، على عكس REST ، ومعظمها لم يعد ملائمًا تمامًا.

ما هو GraphQL


يُعد GraphQL بديلاً عصريًا لواجهة برمجة تطبيقات REST ، والذي يسمح لك بالاستعلام عن البيانات بطريقة أكثر تحسينًا ، مع توفير البيانات التي تحتاجها فقط.

إعداد البيئة


سنقوم بتقديم الطلبات إلى الخادم من خلال Apollo - المكتبة الأكثر شعبية للعمل مع GraphQL في الوقت الحالي.

لنبدأ العمل. بادئ ذي بدء ، دعنا نضيف الأذونات اللازمة للعمل مع الشبكة إلى البيان:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

بعد ذلك ، تحتاج إلى ربط أبولو. نذهب إلى build.gradle الرئيسي وفي قسم التبعيات نضيف السطر التالي:

classpath 'com.apollographql.apollo:apollo-gradle-plugin:2.0.0'

تحتاج الآن إلى إضافة تبعيات إضافية في ملف build.gradle لوحدة التطبيق:

implementation("com.apollographql.apollo:apollo-runtime:2.0.0")
implementation "com.apollographql.apollo:apollo-android-support:2.0.0"

بالإضافة إلى ذلك ، أضف اتصال المكون الإضافي إلى أعلى الملف:

apply plugin: 'com.apollographql.apollo'

بعد مزامنة المشروع ، نحتاج إلى تكوين توليد الأكواد للنماذج التي سنجري بها استعلامات إلى GraphQL.

دعونا تقليل بيئة التطوير وفتح محطة طرفية. انتقل إلى المجلد مع مشروعك:

cd /Users/user/Desktop/ProjectName

إذا لم يكن لديك npm بعد ، فقم بتنزيله أولاً من الموقع الرسمي

Install apollo-codegen - أداة تسمح لك بتنزيل schema.json - وهو ملف يعمل كمصدر أبولو لتوليد النماذج:

npm install apollo-codegen

تنزيل schema.json (يجب أن تكون في دليل مشروعك حيث ظهر مجلد node_modules):

node_modules/.bin/apollo-codegen download-schema https://   api/ --output schema.json

نرى الآن في مجلد المشروع ملف schema.json. يبقى لإظهار ملفات أبولو لتوليد النماذج. للقيام بذلك ، اتبع الخطوات التالية.

انتقل إلى مجلد التطبيق الخاص بمشروعك ، ثم src -> main. هنا نحتاج إلى إنشاء مجلد GraphQL. سنضيف هنا ملفات .graphql.

انسخ الملف الذي تم تنزيله في الخطوة السابقة إلى المجلد الذي تم إنشاؤه - schema.json تم إعداد
البيئة ، انتقل إلى الرمز

توليد كود النموذج


لنبدأ بملفات .graphql. سيتم تخزين الطلبات هنا.
يحتوي GraphQL على نوعين من الاستعلامات:
استعلام - تناظري
لطفرة GET - تناظري POST / PUT / DELETE

افترض أنك تقوم بخدمة لإيداع الضيوف في غرفة في فندق لمسؤولي هذا الفندق. يمكن للتطبيق القيام 3 وظائف. مستخدم تسجيل الدخول (مسؤول) ، احصل على معلومات الغرفة عن طريق المعرف وقم بتعبئة الضيوف

قم بإنشاء ملف loginUser.graphql في دليل التطبيق / src / main / graphQL الذي تم إنشاؤه في القسم السابق. سيؤدي استخدام هذا الملف أبولو إلى إنشاء نموذج لاسم المستخدم.

محتوى الملف:

mutation loginUser($email:String!, $password:String!) {
    login(
        user: {
            email: $email,
            password: $password
        }
    ){
        email,
        token,
        refreshToken
    }
}

بالإضافة إلى ذلك ، نحن بحاجة إلى ملف getRoom.graphql ، بمساعدته يتم إنشاء نموذج للحصول على غرفة الفندق:

query getRoom($room_id: String) {
    room(room_id: $room_id) {
        title,
        room_number,
        cheked_in_family_name,
        has_minibar
    }
}

والملف النهائي هو checkUserIn.graphql. يستخدم أيضًا الطفرة:

mutation checkInFamily($room_id: String!, $family_name: String!) {
    room(
        room: {
            title: $family_name,
            room_id: $room_id
        }
    ){
        room_id,
        family_name,
        minibar_products{
            title,
            weight
        }
    }
}

نحن نبني المشروع ونرى 3 نماذج تم إنشاؤها في مجلد التطبيق / الإنشاء / المولدات / المصدر / أبولو / التصحيح / الخدمة: GetRoomQuery و CheckUserInMutation و LoginUserMutation

تنفيذ الاستعلام


قم بإنشاء فئة واحدة لخدمة NetworkService التي ستوفر لنا ApolloClient. نحن نصنع منه طريقتين. getApolloClient () لتنفيذ الطلبات التي لا تتطلب رمزًا مميزًا أو أي معلمات إضافية ، و getApolloClientWithTokenInterceptor () ، الذي سنقوم فيه بإلقاء الرمز المميز للطلبات:

import com.apollographql.apollo.ApolloClient
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request

class NetworkService {

  fun getApolloClient(): ApolloClient {
    val okHttp = OkHttpClient
      .Builder()
      .build()

    return ApolloClient.builder()
      .serverUrl(BASE_URL)
      .okHttpClient(okHttp)
      .build()
  }

  fun getApolloClientWithTokenInterceptor(token: String): ApolloClient {

    val httpClient = OkHttpClient.Builder()
      .addInterceptor(Interceptor { chain: Interceptor.Chain ->
        val original: Request = chain.request()
        
        val builder: Request.Builder = original
          .newBuilder()
          .method(original.method, original.body)
        
        builder.header("Authorization", "Bearer $token")
        return@Interceptor chain.proceed(builder.build())
      })
      .build()

    return ApolloClient.builder()
      .serverUrl(BASE_URL)
      .okHttpClient(httpClient)
      .build()
  }

  companion object {
    private var mInstance: NetworkService? = null

    fun getInstance(): NetworkService? {
      if (mInstance == null) {
        mInstance = NetworkService()
      }
      return mInstance
    }
  }
}

ننتقل الآن إلى نشاطنا أو جزءنا ، وهنا ننفذ تنفيذ الطلبات. للبدء ، قم بتسجيل الدخول:

  private fun loginUser() {

    val client = NetworkService.getInstance()?.getApolloClient()
    val loginMutation = LoginUserMutation
      .builder()
      .email(emailEdit.text.toString())
      .password(passwordEdit.text.toString())
      .build()

    client
      ?.mutate(loginMutation)
      ?.enqueue(object : ApolloCall.Callback<LoginUserMutation.Data>() {

        override fun onResponse(response: Response<LoginUserMutation.Data>) {
          if (!response.hasErrors()) {
            val token = response.data?.login()?.token()
            val email = response.data?.login()?.email()
            // ,   ui,     
            runOnUiThread {
              //   ,  
            }
          }
        }

        override fun onFailure(e: ApolloException) {}
      })
  }

هذا مثال للعمل مع الطفرة. نفذنا هذا الطلب بدون رمز مميز في العنوان. الآن دعونا نلقي نظرة على مثال للعمل مع الاستعلام ، حاول الحصول على معلومات حول الغرفة. لنفترض أن الغرفة تُمنح لنا فقط باستخدام رمز مميز. نقوم بتنفيذ الطلب على النحو التالي:

  private fun getRoom() {
    val token = "123456"
    val client = NetworkService.getInstance()
      ?.getApolloClientWithTokenIntercetor(token)

    val roomId = "123"
    val allRoomsQuery = GetRoomQuery(Input.fromNullable(roomId))

    client
      ?.query(allRoomsQuery)
      ?.enqueue(object : ApolloCall.Callback<GetRoomQuery.Data>() {

        override fun onResponse(response: Response<GetRoomQuery.Data>) {
          if (!response.hasErrors()) {
            val familyName = response.data?.room()?.family_name()
          }
        }

        override fun onFailure(e: ApolloException) {}
      })
  }

كواجب منزلي ، حاول أن تكتب لنفسك تنفيذًا لتسوية الضيوف.

روابط مفيدة:

توثيق apollo-client للأندرويد
Github apollo-client android

All Articles