1. 程式人生 > 實用技巧 >android okhttp + retrofit使用

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 ,使用者的一些基本資訊和登入憑證資訊

接下來我們開始使用

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())
        }
    }
}