跳槽快兩個月了,到了一家新公司,正準備開幹,結果發現公司服務端用的是apollo-graphql來處理客戶端網絡請求,就要求客戶端也用這個graphql,當時還挺奇怪的,畢竟以前android客戶端用的都是retrofit+okhttp+rxjava這一套,我特麼還吭哧吭哧的將它們封裝了一套自認爲挺不錯的網絡層架構。結果來到新公司發現就這麼用不上了(其實一部分是用的上的,後面再說);如今幹Android開發的,處理網絡請求這塊,不說百分百,也有個百分之七八十用的都是這一套吧,其它的基本也是OKHttp的封裝庫;儘管個人心裏裏有一萬隻草泥馬在奔騰,但仍是得迎難而上啊。不過有一說一,網上關於在Android上使用graphql的文章真的少的可憐,其實從這個庫的star數量也能看出來。
阿里P6P7【安卓】進階資料分享+加薪跳槽必備面試題前端
你們要是使用過Postman的話,不知有沒有注意到它也開始支持graphql了。java
(透露下,其實apollo-android庫網絡層也是使用的OKHttp,可見OKHttp的強大啊)react
在理解graphql以前先闡述下RESTful,由於graphql產生的緣由就是想替代RESTful。咱們都知道服務端如今大部分使用的都是基於RESTful的設計風格和開發方式,固然客戶端也是這樣(Retrofit就是一個相似於RESTful的網絡框架),那到底怎麼理解RESTful呢?首先REST不是英語單詞rest(休息)的意思,而是Representational State Transfer的簡稱,即表現層狀態轉移,其中REST指的是一組架構約束條件和原則,只要某個架構符合REST的約束條件和原則,那就能夠稱爲RESTful架構,它是一種軟件架構風格,而不是標準,也就是說不是強制的。看完這些拗口的術語你可能仍是不太清楚,用知乎大神lvony的一句話歸納。android
用URL定位資源,用HTTP動詞(GET,POST,DELETE,PUT)描述操做
REST的主體是資源,好比網絡上的一張圖片,一段文字,一個視頻,一些實際存在的東西,而URL就是用來指向這個資源的,好比:面試
https://www.baidu.com/user
這個api一看就是用來對user資源的操做,這裏使用名詞來指定資源,沒有涉及操做相關的聲明,爲啥呢?由於基本的操做有增刪改查,若是你不用restful的話,就會產生四個接口:數據庫
https://www.baidu.com/add_user https://www.baidu.com/update_user https://www.baidu.com/delete_user https://www.baidu.com/query_user
顯然這種設計風格太冗餘了,那讓咱們切換到restful會是什麼樣呢?對資源的操做無外乎增刪改查,在restful中,每個HTTP動詞描述一種操做:json
這樣咱們只須要一個接口就好了。有的同窗可能有疑問了,實際開發中不少查詢操做都是使用post,而不是get,由於有些查詢須要的參數特別多,若是使用get,接口會很難看,同時也不安全;那我這裏就不是RESTful了嗎?其實上面說過了,RESTful是一種軟件架構風格,沒有強制約束,也就是說只是建議開發者這樣作,適當的變通沒有問題。在知乎上還看到一種對RESTful的經典解釋。後端
看http url就知道要什麼 看http method就知道幹什麼 看http status code就知道結果如何
前面兩句和lvony說的一個意思,後面一句也很精髓,http狀態不少,看到其中的一些狀態碼你就明白請求結果如何。api
/ 初識 GraphQL /GraphQL 是 Facebook 於 2012 年在內部開發的數據查詢語言,在 2015 年開源, 旨在提供 RESTful 架構體系的替代方案 GraphQL能夠當作是Graph+QL,其中QL是Query Language的簡稱, 因此GraphQL的意思是可視化(圖形化)查詢語言,是一種描述客戶端如何向服務端請求數據的API語法。相似於RESTful API 規範 想一想SQL(Structured Query Language) 是結構化查詢語言的簡稱, 你應該大概理解GraphQL是啥了,可是要注意,雖然GraphQL名字叫查詢語言,可是跟數據庫其實沒啥關係。當數據從MySQL、NoSQL等數據庫裏面查出來,怎麼給前端或者移動端呢?這時候GraphQL站出來了,它做用於數據接口,讓客戶端自由篩選獲取服務端事先定好的數據,提升了api接口的靈活性,好比後端從數據查詢出來A,B,C,D四個字段,使用GraphQL處理接口,這樣客戶端來獲取數據,能夠隨意要哪幾個字段,能夠是A,能夠是B,也能夠是B,C等,不須要再跟服務端哥們打招呼了。再說說移動端使用GraphQL的緣由吧:瞭解了基於RSTful風格的網絡請求,咱們應該能知道某些狀況下其實會產生一些弊端的。緩存
固然了還有其它的缺點,這裏就不細說了,而這些問題在apollo graphql中都不存在。
Graphql只是一種用於 API 的查詢語言,相比於REST API,查詢多個數據就須要多個URL不一樣,它能夠作到用一個請求能準確的獲取你所須要的全部數據,很少很多。/ 使用 GraphQL /說了這麼多,來看看怎麼在Android項目裏接入GraphQL吧!GraphQL有不少版本,如圖。
其中支持Android平臺的庫就是apollo-android,使用這個庫要求gradle版本是5.1.1或者更高,一開始讓我使用這個庫的時候,我還擔憂它支持OKHttp嗎?支持RxJava嗎?後來正式接入的時候才發現是我多想了,這個庫底層的網絡模塊使用的也是OKHttp,同時也支持RxJava,瞬間感受:喲,小老弟,不錯嘛~第一步:這裏我新建一個工程,第一步要作的事就是在項目根目錄下的build.gradle裏添加插件依賴:
dependencies { classpath 'com.apollographql.apollo:apollo-gradle-plugin:1.2.1' }
第二步:接下來在app module的build.gradle裏添加插件依賴和庫依賴,記住插件依賴必定要在Android插件後面:
apply plugin: 'com.apollographql.android' dependencies { implementation 'com.apollographql.apollo:apollo-runtime:1.2.1' }
第三步:若是要使用RxJava(確定要使用咯),還須要添加apollo-rx2-support。
dependencies { implementation ('com.apollographql.apollo:apollo-rx2-support:1.2.1') implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' }
rxjava這個庫不須要添加,apollo-rx2-support庫已經依賴了。第四步:由於apollo插件會根據.graphql文件和schema.json文件生成java代碼,而代碼生成器會使用到jetbrains annotations,因此還須要添加依賴。
dependencies { compileOnly 'org.jetbrains:annotations:13.0' testCompileOnly 'org.jetbrains:annotations:13.0'//可選 }
接下來就是添加上面提到的.graphql文件和schema.json文件了,這兩個配置文件實際開發中是由後端開發提供給你的,而且這兩個文件要求一一對應。
接下來build工程,在app/build/generated/source/apollo/classes/debug下面找到生成的幾個文件(經過官網的.graphql文件和schema.json文件生成的),如圖:
這裏簡單看下.graphql文件裏面的內容。
query FeedQuery($type: FeedType!, $limit: Int!) { feedEntries: feed(type: $type, limit: $limit) { id repository { ...RepositoryFragment } postedBy { login } } } fragment RepositoryFragment on Repository { name full_name owner { login } }
先看第一句:
query FeedQuery($type: FeedType!, $limit: Int!)
而後看第二句:
feedEntries: feed(type: $type, limit: $limit)
繼續看裏面的結構。
{ id repository { ...RepositoryFragment } postedBy { login } }
fragment RepositoryFragment on Repository { name full_name owner { login } }
使用fragment修飾,當你的返回數據中字段比較多時,就可使用fragment來組織一組字段,便於複用。第五步:初始化ApolloClient。之前咱們都是使用Retrofit+OKHttp,如今變成了Apollo+OKHttp。
OkHttpClient okHttpClient = new OkHttpClient.Builder() .build(); ApolloClient apolloClient = ApolloClient.builder() .serverUrl(BASE_URL) .okHttpClient(okHttpClient) .build();
第六步:發起請求。使用apollo構建請求和使用okhttp有點相似,還記得在okhttp裏如何發起一個請求嗎?是否是構建一個Request,而後實例化一個Call,最後發起請求;在apollo裏也是這樣。
//Limit 和 Type是咱們graphQL 查詢中的動態參數,在.graphql文件裏定義的 FeedQuery feedQuery = FeedQuery .builder() .limit(10) .type(FeedType.HOT) .build(); ApolloQueryCall<FeedQuery.Data> queryCall = apolloClient.query(feedQuery); queryCall.enqueue(new ApolloCall.Callback<FeedQuery.Data>() { @Override public void onResponse(@NotNull Response<FeedQuery.Data> response) { FeedQuery.Data data = response.data(); List<FeedQuery.FeedEntry> feedEntries = data.feedEntries(); for (FeedQuery.FeedEntry feedEntry : feedEntries) { Log.i("MainActivity",""+feedEntry.toString()); } } @Override public void onFailure(@NotNull ApolloException e) { Log.i("MainActivity","onFailure " + e.getMessage()); } });
響應中的FeedQuery.FeedEntry內容以下:
feedEntries={ id = 105, repository = Repository { fragments = Fragments { repositoryFragment = RepositoryFragment { name = pairhub, full_name = pairhub / pairhub, owner = Owner { login = pairhub } } } }, postedBy = PostedBy { login = gustavlrsn } }
第七步:結合RxJava使用以下:
FeedQuery feedQuery = FeedQuery .builder() .limit(10) .type(FeedType.HOT) .build(); Rx2Apollo.from(apolloClient.query(feedQuery)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new DefaultObserver<Response<FeedQuery.Data>>(){ @Override public void onNext(Response<FeedQuery.Data> dataResponse) { FeedQuery.Data data = dataResponse.data(); List<FeedQuery.FeedEntry> feedEntries = data.feedEntries(); for (FeedQuery.FeedEntry feedEntry : feedEntries) { Log.i("MainActivity","feedEntry:"+feedEntry.toString()); } } @Override public void onError(Throwable e) { Log.i("MainActivity","onError " + e.getMessage()); } @Override public void onComplete() { } });
主要是將ApolloCall(ApolloQueryCall的父類)轉成Observable類型,還有其它類型轉換,以下表:
轉換例子以下:
ApolloCall<FeedQuery.Data> apolloCall = apolloClient.query(query); Observable<Response<FeedQuery.Data>> observable = Rx2Apollo.from(apolloCall); ApolloPrefetch<FeedQuery.Data> apolloPrefetch = apolloClient.prefetch(query); Completable completable = Rx2Apollo.from(apolloPrefetch);
也能夠轉成Disposable類型:
Disposable disposable = Rx2Apollo.from(query).subscribe(); disposable.dispose();
關於graphql的使用還有不少,好比支持數據庫緩存,http緩存,文件上傳等,它能極大的簡化咱們的接口請求及讓接口定義更加的自由,開放。
阿里P6P7【安卓】進階資料分享+加薪跳槽必備面試題