Retrofit+rxjava进行网络请求

1.2 Get请求

public interface GetWeatherService { @GET("weather_mini") Call<WeatherEntity> getMessage(@Query("city") String city); }

在MianActivity中 我们写在initOnlyRetrofit()方法中,如下:

/** * 只有Retrofit的联网请求 */ private void initOnlyRetrofit() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://wthrcdn.etouch.cn/")//基础URL 建议以 / 结尾 .addConverterFactory(GsonConverterFactory.create())//设置 Json 转换器 .build(); GetWeatherService weatherService = retrofit.create(GetWeatherService.class); Call<WeatherEntity> call = weatherService.getMessage("北京"); call.enqueue(new Callback<WeatherEntity>() { @Override public void onResponse(Call<WeatherEntity> call, Response<WeatherEntity> response) { Log.e(TAG, "response == " + response.body().getData().getGanmao()); } @Override public void onFailure(Call<WeatherEntity> call, Throwable t) { Log.e(TAG, "Throwable : " + t); } }); }

运行一下我们可以看到打印结果如下:

二.RxJava 与 Retrofit

2.1 同样先添加依赖(新增的)

compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'io.reactivex:rxandroid:1.2.1' compile 'io.reactivex:rxjava:1.2.1'

2.2 这时将Retrofit与RxJava 链接起来只需这样修改.

在Retrofit Builder链表中如下调用addCallAdapterFactory

Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://wthrcdn.etouch.cn/")//基础URL 建议以 / 结尾 .addConverterFactory(GsonConverterFactory.create())//设置 Json 转换器 .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//RxJava 适配器 .build();

2.3 这样一来我们定义的service返回值就不在是一个Call了,而是一个Observable ,那我们需重新定义接口

public interface GetWeatherService { @GET("weather_mini") Observable<WeatherEntity> getRxMessage(@Query("city") String city); }

2.4 重新定以后你的Service接口现在可以作为Observable返回了.我们需要用RxJava方式实现网络请求,可以完全像RxJava那样使用它.

GetWeatherService weatherService = retrofit.create(GetWeatherService.class); weatherService.getRxMessage("北京") .subscribeOn(Schedulers.io())//IO线程加载数据 .observeOn(AndroidSchedulers.mainThread())//主线程显示数据 .subscribe(new Subscriber<WeatherEntity>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(WeatherEntity weatherEntity) { Log.e(TAG,"RxJava + Retrofit= " + weatherEntity.getData().getGanmao()); } });

subscribeOn(): 指定 subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。或者叫做事件产生的线程。

observeOn(): 指定 Subscriber 所运行在的线程。或者叫做事件消费的线程。

2.5 这里实现基本的网络请求了,我们来看下打印日志.

嗯,联网实现了,我看可以考虑收工啦~~~ 纳尼? 说好的缓存呢?dialog呢?还有取消请求我该怎么做? 嗯,嗯,别捉急,我开个玩笑,马上带来重头戏.

三.缓存的实现

在Retrofit 2.0中,OkHttp 是必须的,并且自动设置为了依赖。也就说我们不用在build.gradle添加依赖了。下面的代码是从Retrofit 2.0的pom文件中抓取的。

com.squareup.okhttp

okhttp

为了让OkHttp 的Call模式成为可能,在Retrofit 2.0中OkHttp 自动被用作HTTP 接口。此时我们要在OkHttpClient里设置缓存,添加拦截器.那OkHttpClient在Retrofit里怎么设置呢.其实只需添加一句,在retrofit链式调用中调用client(OkHttpClient client)方法即可,来看下代码:

OkHttpClient mClient = new OkHttpClient.Builder() .addInterceptor(mInterceptor)//应用程序拦截器 .addNetworkInterceptor(mNetInterceptor)//网络拦截器 .cache(mCache)//添加缓存 .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .client(mClient)//添加OK .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();

OkHttpClient我们分别添加了3方法.

.cache(mCache)用于添加缓存;

.addInterceptor(mInterceptor)应用程序拦截器;

.addNetworkInterceptor(mNetInterceptor)网络拦截器;

3.1 OkHttp本身是有缓存这个东西的,只是如果你不去设置,是不起作用的 我们需要设置.cache()去添加缓存

File mFile = new File(context.getCacheDir() + "http");//储存目录 long maxSize = 10 * 1024 * 1024; // 10 MB 最大缓存数 Cache mCache = new Cache(mFile, maxSize);

3.2 这里设置了缓存和目录还是不够的,我们还需要设置拦截器Interceptors

先来看看Interceptor本身的文档解释:观察,修改以及可能短路的请求输出和响应请求的回来。通常情况下拦截器用来添加,移除或者转换请求或者回应的头部信息。 拦截器接口中有intercept(Chain chain)方法,同时返回Response。

chain.proceed(request)是拦截器的关键部分。这个看似简单的方法是所有的HTTP工作发生的地方,产生满足要求的反应。 拦截器可以链接。假设你有一个压缩的拦截和校验拦截器:你需要决定数据是否被压缩,或者校验或校验然后压缩。okhttp使用列表来跟踪和拦截,拦截器会按顺序调用。

3.3 拦截器可以注册为应用程序拦截或网络拦截

每种拦截器chain有相对的优势。

Application interceptors(应用拦截器)

  • 1.不必担心中间的responses,例如重定向和重连。

  • 2.总是调用一次,即使是从缓存HTTP响应。

  • 3.观察应用程序的原始意图。不关心OkHttp的注入headers,例如If-None-Match

  • 4.允许短路和不执行Chain.proceed().

  • 5.允许重连,多次调用proceed()。

.

Network Interceptors (网络拦截器)

  • 1.能够操作中间反应,例如重定向和重连。

  • 2.不能被缓存响应,例如短路网络调用。

  • 3.观察数据,正如它将在网络上传输。

  • 4.有权使用携带request的Connection

具体2种选择器用哪种大家酌情考虑即可。说了这么多,拦截Interceptor到底该怎么写?下面个给出拦截器的代码片段。

private static final int NET_MAX = 30; //30秒 有网超时时间 private static final int NO_NET_MAX = 60 * 60 * 24 * 7; //7天 无网超时时间 //网络拦截器 Interceptor mNetInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Log.e("TAG", "拦截 应用 缓存"); Request request = chain.request(); if (!NetWorkUtils.networkIsAvailable(context)) {//判断网络状态 无网络时 request = request.newBuilder() //Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。为了确保缓存生效 .removeHeader("Pragma") .header("Cache-Control", "private, only-if-cached, max-stale=" + NO_NET_MAX) .build(); } else { request = request.newBuilder() //Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。为了确保缓存生效 .removeHeader("Pragma") .header("Cache-Control", "private, max-age=" + NET_MAX)//添加缓存请求头 .build(); } return chain.proceed(request); } };

这里NetWorkUtils.networkIsAvailable(context)是判断网络状态的工具类,大家可以去源码里找,这里就不在给出.

3.4 Okhttp的缓存由返回的header 来决定,用”Cache-control”来控制,常见的取值有private、no-cache、max-age、must-revalidate等,默认为private。

  • public 所有内容都将被缓存

  • private 内容只缓存到私有缓存中

  • no-cache 所有内容都不会被缓存

  • no-store 所有内容都不会被缓存到缓存或 Internet 临时文件中

  • must-revalidation/proxy-revalidation 如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证

  • max-age=xxx (xxx is numeric) 缓存的内容将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较高

  • 在某些情况下,如用户单击“刷新”按钮,就可能有必要跳过缓存,并直接从服务器获取数据。要强制刷新,添加无缓存指令:”Cache-Control”: “no-cache”。
  • 如果缓存只是用来和服务器做验证,可是设置更有效的”Cache-Control”:”max-age=0”。

  • 有时你会想显示可以立即显示的资源。这是可以使用的,这样你的应用程序可以在等待最新的数据下载的时候显示一些东西, 重定向request到本地缓存资源,添加”Cache-Control”:”only-if-cached”。

  • 有时候过期的response比没有response更好,设置最长过期时间来允许过期的response响应:int maxStale = 30; // 30秒 “Cache-Control”:”max-stale=” + maxStale。

缓存的实现到这里就讲完了,可能代码片段让你看的头晕目眩,那给大家一个简单封装了的完整代码

package com.aaron.rxjava_retrofit.net; import android.content.Context; import android.util.Log; import com.aaron.rxjava_retrofit.utils.NetWorkUtils; import java.io.File; import java.io.IOException; import okhttp3.Cache; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import retrofit2.Retrofit; import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; /** * 作者:哇牛Aaron * 作者简书文章地址: http://www.jianshu.com/users/07a8b5386866/latest_articles * 时间: 2016/11/24 * 功能描述: */ public class HttpUtils { private static final String URL_WEATHER = "http://wthrcdn.etouch.cn/"; private static final int NET_MAX = 30; //30秒 有网超时时间 private static final int NO_NET_MAX = 60 * 60 * 24 * 7; //7天 无网超时时间 public static Retrofit getRetrofit(String url, final Context context) { //应用程序拦截器 Interceptor mInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Log.e("TAG", "拦截 网络 缓存"); Request request = chain.request(); if (!NetWorkUtils.networkIsAvailable(context)) {//判断网络状态 无网络时 Log.e("TAG", "无网~~ 缓存"); request = request.newBuilder() //Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。为了确保缓存生效 .removeHeader("Pragma") .header("Cache-Control", "private, only-if-cached, max-stale=" + NO_NET_MAX) .build(); } else {//有网状态 Log.e("TAG", "有网~~ 缓存"); request = request.newBuilder() //Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。为了确保缓存生效 .removeHeader("Pragma") .header("Cache-Control", "private, max-age=" + NET_MAX)//添加缓存请求头 .build(); } return chain.proceed(request); } }; //网络拦截器 Interceptor mNetInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Log.e("TAG", "拦截 应用 缓存"); Request request = chain.request(); if (!NetWorkUtils.networkIsAvailable(context)) {//判断网络状态 无网络时 request = request.newBuilder() //Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。为了确保缓存生效 .removeHeader("Pragma") .header("Cache-Control", "private, only-if-cached, max-stale=" + NO_NET_MAX) .build(); } else { request = request.newBuilder() //Pragma:no-cache。在HTTP/1.1协议中,它的含义和Cache-Control:no-cache相同。为了确保缓存生效 .removeHeader("Pragma") .header("Cache-Control", "private, max-age=" + NET_MAX)//添加缓存请求头 .build(); } return chain.proceed(request); } }; File mFile = new File(context.getCacheDir() + "http");//储存目录 long maxSize = 10 * 1024 * 1024; // 10 MB 最大缓存数 Cache mCache = new Cache(mFile, maxSize); OkHttpClient mClient = new OkHttpClient.Builder() .addInterceptor(mInterceptor)//应用程序拦截器 .addNetworkInterceptor(mNetInterceptor)//网络拦截器 .cache(mCache)//添加缓存 .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .client(mClient)//添加OK .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); return retrofit; } public static GetWeatherService createWeatherService(Context context) { return getRetrofit(URL_WEATHER, context).create(GetWeatherService.class); } }

在MainActivity中调用

HttpUtils.createWeatherService(MainActivity.this).getRxMessage("北京") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<WeatherEntity>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(WeatherEntity weatherEntity) { Log.e(TAG, "Cache RxJava + Retrofit= " + weatherEntity.getData().getGanmao()); } });

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

小福利:

在当下这个碎片化信息环境的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021大厂最新Android面试真题解析

Android大厂面试真题解析

各个模块学习视频:如数据结构与算法

算法与数据结构资料图

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。
一线互联网架构师

这份体系学习笔记,适应人群:**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!点赞+评论即可获得!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

提高自己的技术。
[外链图片转存中…(img-xYjeFMTJ-1712796712501)]

[外链图片转存中…(img-mUk9neSs-1712796712501)]

这份体系学习笔记,适应人群:**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!点赞+评论即可获得!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值