跳槽快两个月了,到了一家新公司,正准备开干,结果发现公司服务端用的是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【安卓】进阶资料分享+加薪跳槽必备面试题