zoukankan      html  css  js  c++  java
  • android okhttp + retrofit使用

    首先需要引入依赖

    implementation 'com.squareup.okhttp3:okhttp:4.8.0'
    implementation 'com.squareup.okio:okio:2.7.0'
    
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.google.code.gson:gson:2.8.6'

    首先我们创建一个okhttpmanager单例类,为了获取okhttpclient

    val builder = OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .sslSocketFactory(
            SSLSocketClient.getSSLSocketFactory(),
            SSLSocketClient.getTrustManager()[0] as X509TrustManager
        )
               
        .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
        //cookieJar 处理okhttp和webview cookie同步
        //.cookieJar(WebViewCookieHandler(context))
        .cache(Cache(File(context.externalCacheDir, "okHttpCache"), Globals.REQUEST_CACHE_SIZE))
    
    //拦截器,处理访问时携带的参数
    builder.addInterceptor {
        val httpUrl = it.request().url
        val httpMainUrl = context.getString(R.string.url).toHttpUrlOrNull()
        val request: Request = 
        if (httpUrl.host == httpMainUrl!!.host) {
            it.request().newBuilder()
                    .addHeader("authenticate", MyApp.instance.userInfo().token ?: "")
                    .build()
        } else {
            it.request()
        }
        it.proceed(request)
    }
    
    //拦截器 退出拦截
    builder.addInterceptor {
        val request = it.request()
        val response = it.proceed(request)
        //这里约定后台返回401状态码,就表示没有登录状态了
        if (response.code == 401) {
            //这里需要进行退出系统处理
            return@addInterceptor response.newBuilder().build()
        }
        return@addInterceptor response
    }
    
    //这样就获取到okhttpclient了
    builder.build()

    这里贴上上面用到的 SSLSocketClient类

    public class SSLSocketClient {
    
        private static final List<String> VERIFY_HOST_NAME_ARRAY = new ArrayList<String>(){{
            add("www.test.com");
        }};
    
        //获取这个SSLSocketFactory
        public static SSLSocketFactory getSSLSocketFactory() {
            try {
                //SSLContext sslContext = SSLContext.getInstance("SSL");
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, getTrustManager(), new SecureRandom());
                return sslContext.getSocketFactory();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        //获取TrustManager
        public static TrustManager[] getTrustManager() {
            return new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] chain, String authType) {
                        }
    
                        @Override
                        public void checkServerTrusted(X509Certificate[] chain, String authType) {
                        }
    
                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[]{};
                        }
                    }
            };
        }
    
        //获取HostnameVerifier
        public static HostnameVerifier getHostnameVerifier() {
            return (s, sslSession) -> {
                if(TextUtils.isEmpty(s)){
                    return false;
                }
                return !Arrays.asList(VERIFY_HOST_NAME_ARRAY).contains(s);
            };
        }
    
    }

    然后我们开始写retrofitclient类

    class RetrofitClient private constructor() {
    
        private lateinit var retrofit: Retrofit
    
        companion object {
            val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
                RetrofitClient()
            }
        }
    
        init {
            createRetrofit()
        }
    
        private fun createRetrofit() {
            retrofit = Retrofit.Builder().baseUrl("https://www.test.com/web-api/")
                .client(OkHttpManager.instance.client())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build()
        }
    
        fun <T> getService(service: Class<T>): T {
            return retrofit.create(service)
        }
    
    }

     然后定义api

    interface LoginApi {
        @PUT("login")
        fun login(@Query("username") username :String,@Query("pass") pass :String):Observable<ResponseWrapper<LoginRespBean>>
    }

    @GET get请求  @POST post请求   @PUT put 请求   @DELETE delete请求

    一般put请求我们一般会使用@Body传递     比如  @Body loginBean:LoginBean      LoginBean(username,pass)    

    @Path      [@GET("user/{id}")  fun userInfo(@Path("id") uid:String) ]

    LoginRespBean 定义的用户的唯一ID ,用户的一些基本信息和登录凭证信息

    ResponseWrapper类
    data class ResponseWrapper<out T>(val code: Int, val msg: String, val data: T)

    接下来我们开始使用

    RetrofitClient.instance.getService(LoginApi::class.java)
        .login("用户名", "密码")
        .compose(NetworkScheduler.compose())
        .subscribe({
            if (it.code == RespCode.OK) {
                 //登录成功
            } else {
                  //登录失败
            }
    }, {
        //出现异常了  
        //这里异常的代码块,我们不能省略,可以空实现,如果配置了全局异常处理,异常处理的代码块可以省略掉  
    //subscribe {}
    }) //这里贴一下全局异常处理 这个代码放到自定义的application类中即可 RxJavaPlugins.setErrorHandler { MyLog.e("RxJava统一错误处理", "======" + it.message) }
    NetworkScheduler类
    object NetworkScheduler {
        fun <T> compose(): ObservableTransformer<T,T>{
            return ObservableTransformer {
                it.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            }
        }
    }
     
  • 相关阅读:
    vuex 数据持久化
    vue中通过第三方代理解决跨域问题
    谷歌浏览器格式化插件
    mongodb安装配置
    Nodejs express中创建ejs项目
    elementui tree 组件实现鼠标移入节点,节点后面显示添加删除按钮
    iframe页面无法跳转问题
    elementui table组件,根据数据的不同,显示不同的内容
    elementui tree组件自定义图标
    Aborting a running program
  • 原文地址:https://www.cnblogs.com/rchao/p/13367910.html
Copyright © 2011-2022 走看看