美文网首页
retrofit使用

retrofit使用

作者: 有点健忘 | 来源:发表于2018-07-06 15:12 被阅读20次

    这玩意平时弄一次就不管了,时间久了就忘了。
    收藏几个帖子,忘了拿来看看
    https://www.jianshu.com/p/0fda3132cf98

    https://www.jianshu.com/p/308f3c54abdd
    官方的https://github.com/square/retrofit
    文档https://square.github.io/retrofit/

    相关库

        // Okhttp库,可以省略,retrofit自带了
        //implementation 'com.squareup.okhttp3:okhttp:3.10.0'
     // implementation 'io.reactivex.rxjava2:rxjava:2.1.12' //省略,已经自带了
        // Retrofit库
        implementation 'com.squareup.retrofit2:retrofit:2.4.0'
        implementation "com.squareup.retrofit2:converter-gson:2.4.0"
        implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
        implementation 'com.google.code.gson:gson:2.8.2'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' //如果需要打印log的话需要这个
    

    一般都用的gson解析,万一用别的看下

    数据解析器 Gradle依赖
    Gson com.squareup.retrofit2:converter-gson:2.0.2
    Jackson com.squareup.retrofit2:converter-jackson:2.0.2
    Simple XML com.squareup.retrofit2:converter-simplexml:2.0.2
    Protobuf com.squareup.retrofit2:converter-protobuf:2.0.2
    Moshi com.squareup.retrofit2:converter-moshi:2.0.2
    Wire com.squareup.retrofit2:converter-wire:2.0.2
    Scalars com.squareup.retrofit2:converter-scalars:2.0.2

    网上找了个缓存的代码,结果加载一次数据以后,我把网断了,再进去测试结果挂了

    retrofit cache 504 Unsatisfiable Request (only-if-cached) error

    cookie的使用这里写了参考文章,需要的话可以去看
    https://www.cnblogs.com/Jason-Jan/p/8010795.html
    我下边用的hy的https://github.com/hongyangAndroid/okhttputils 我把里边cookie的类copy到工程里了。

    封装的带缓存的代码

    import com.charliesong.wanandroid.retrofit.cookie.CookieJarImpl
    import com.charliesong.wanandroid.retrofit.cookie.PersistentCookieStore
    import okhttp3.*
    import retrofit2.Retrofit
    import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
    import retrofit2.converter.gson.GsonConverterFactory
    import okhttp3.logging.HttpLoggingInterceptor
    import java.io.File
    import java.util.concurrent.TimeUnit
    
    
    object MyAPIManager {
    
        private val host = "http://www.wanandroid.com"
        private fun getRetrofit(): Retrofit {
            //缓存容量
            val SIZE_OF_CACHE = (50 * 1024 * 1024).toLong() // 10 MiB
            //缓存路径
            val cacheFile = "${MyApplication.getApp().getCacheDir()}/http"
            val cache = Cache(File(cacheFile), SIZE_OF_CACHE)
            // Cookie 持久化
    //        val cookieJar = PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(InitApp.AppContext))
            //利用okhttp实现缓存
            val clientBuilder = OkHttpClient.Builder()
                    .cookieJar(CookieJarImpl(PersistentCookieStore(MyApplication.getApp())))
    //                //有网络时的拦截器
                    .addNetworkInterceptor(rewrite_response_interceptor)
    //                //没网络时的拦截器
                    .addInterceptor(rewrite_response_interceptor_offline)
                    .cache(cache)
    //                .connectTimeout(10, TimeUnit.SECONDS)
    //                .readTimeout(15, TimeUnit.SECONDS)
    //                .writeTimeout(15, TimeUnit.SECONDS)
    //                .retryOnConnectionFailure(true)
            if (BuildConfig.DEBUG) {
                val interceptor = HttpLoggingInterceptor()
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
                clientBuilder.addInterceptor(interceptor)
            }
            return Retrofit.Builder().baseUrl(host)
                    .client(clientBuilder.build())
                    .addConverterFactory(GsonConverterFactory.create()) //结果解析为gson对象用这个
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) //如果要用rx接口返回Observable加上这个
                    .build()
        }
    
        private var myAPI: MyAPI? = null
        fun getAPI(): MyAPI {
            return myAPI ?: getRetrofit().create(MyAPI::class.java)
        }
    
        private val rewrite_response_interceptor = Interceptor { chain ->
            val originalResponse = chain.proceed(chain.request())
    
            //如果接口里写了@Headers("Cache-Control: max-age=60")缓存时间,那么可以用下边的代码把接口的缓存时间添加到相应的结果里。
    //        var requestCacheControl = chain.request().header("Cache-Control")
    //        var haveSetCacheTime = requestCacheControl != null && (requestCacheControl.contains("max-age"))
    //        if (haveSetCacheTime) {
    //            return@Interceptor originalResponse.newBuilder()
    //                    .addHeader("Cache-Control",requestCacheControl)
    //                    .removeHeader("Pragma").build()
    //        }
            val cacheControl = originalResponse.header("Cache-Control")
            //这里判断的都是服务器返回的缓存条件
            if (cacheControl == null || cacheControl.contains("no-store") || cacheControl.contains("no-cache") ||
                    cacheControl.contains("must-revalidate") || cacheControl.contains("max-age=0")) {
                var build = originalResponse.newBuilder()
                        .removeHeader("Pragma")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效
                        .removeHeader("Cache-Control")
                        .header("Cache-Control", "public, max-age=" + 5)//单位是秒,就是5秒内不请求服务器
    
                build.build()
            } else {
                originalResponse
            }
        }
    
        private val rewrite_response_interceptor_offline = Interceptor { chain ->
            var request = chain.request()
            if (!NormalUtil.isNetworkConnected(MyApplication.getApp())) {
                request = request.newBuilder()
    //                    .header("Cache-Control", "public, only-if-cached")//这个不靠谱,没网络的时候不加载缓存
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build()
            }
            var originalResponse = chain.proceed(request)
            if (NormalUtil.isNetworkConnected(MyApplication.getApp())) {
    //            val cacheControl = request.cacheControl().toString()
    //            originalResponse.newBuilder()
    //                    .header("Cache-Control", "public, max-age=" + 0)//单位是秒
    //                    .removeHeader("Pragma")
    //                    .build()
                originalResponse
            } else {
                val maxTime = 4 * 24 * 60 * 60
                originalResponse.newBuilder()
                        //这里的设置的是我们的没有网络的缓存时间,想设置多少就是多少。
                        .header("Cache-Control", "public, only-if-cached, max-stale=$maxTime")
                        .removeHeader("Pragma")
                        .build()
    
            }
        }
    
    }
    

    简单说明下

    如果我在代码里添加了缓存的header如下

     @Headers("Cache-Control: max-age=60")
        @GET("/article/list/{page}/json")
    

    那么如何生效?
    可以在addNetworkInterceptor这个interceptor里处理
    var requestCacheControl=chain.request().header("Cache-Control")
    就可以获取到header了,完事我们可以判断里边有没有设置max-age,如果设置了,那下边就用这个值,可以参考上边代码里注释的部分
    比如说每日推荐的接口,每天我们可能就推荐一篇文章,那么这个缓存时间可以设置大点。

    2个拦截器的说明

    addNetworkInterceptor添加的是网络拦截器,他会在在request和resposne是分别被调用一次,addinterceptor添加的是aplication拦截器,他只会在response被调用一次
    看这里https://blog.csdn.net/u010286855/article/details/52608485

    常用的api写法

    下边有path占位用,还有query和querymap,用来拼接问号后的参数

     @GET("/article/list/{page}/json")
        fun getTreeArticle(@Path("page") page: Int, @Query("cid") cid: Int):Call<BaseListData<ArticleBean>>
    
        /**如果问号后有多个参数,可以使用map,省事*/
        @GET("/article/list/{page}/json")
        fun getTreeArticle2(@Path("page") page: Int, @QueryMap map:HashMap<String,Int>):Call<BaseListData<ArticleBean>>
    

    登陆返回的信息cookie

    wanandroid D/OkHttp: Server: Apache-Coyote/1.1
    wanandroid D/OkHttp: Set-Cookie: JSESSIONID=5FB89C5317F08DED80500938CD01AEA1; Path=/; HttpOnly
    wanandroid D/OkHttp: Set-Cookie: loginUserName=12345678912; Expires=Sat, 04-Aug-2018 09:29:37 GMT; Path=/
    wanandroid D/OkHttp: Set-Cookie: loginUserPassword=aaaaaa; Expires=Sat, 04-Aug-2018 09:29:37 GMT; Path=/
    wanandroid D/OkHttp: Content-Type: application/json;charset=UTF-8
    wanandroid D/OkHttp: Transfer-Encoding: chunked
    wanandroid D/OkHttp: Date: Thu, 05 Jul 2018 09:29:37 GMT
    wanandroid D/OkHttp: Cache-Control: public, max-age=5000
    wanandroid D/OkHttp: {"data":{"collectIds":[],"email":"","icon":"","id":7280,"password":"aaaaaa","type":0,"username":"12345678912"},"errorCode":0,"errorMsg":""}
    

    相关文章

      网友评论

          本文标题:retrofit使用

          本文链接:https://www.haomeiwen.com/subject/eoubyftx.html