Android 網路訪問框架retrofit2,okhttp3之簡單封裝,kotlin原始碼
阿新 • • 發佈:2019-01-04
本文章需要用到的引用
//okhttp compile 'com.squareup.okhttp3:okhttp:3.8.0' //retrofit compile 'com.squareup.retrofit2:retrofit:2.3.0' //rxjava compile 'io.reactivex.rxjava2:rxjava:2.0.7' //rxjava介面卡,方便rxjava與retrofit的結合 compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' //Log攔截器,方便DEBUG模式輸出log資訊 compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'//json轉換器,方便將返回的資料轉換為json格式 compile 'com.squareup.retrofit2:converter-gson:2.3.0' //rxandroid compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'com.github.bumptech.glide:glide:3.7.0'
定義:
1.基於retrofit2和okhttp3的網路訪問簡單封裝。
基本封裝類
RetrofitClient.kt
import android.content.Context import android.util.Log import java.io.File import okhttp3.Cache import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.converter.gson.GsonConverterFactory import retrofit2.Retrofit import okhttp3.logging.HttpLoggingInterceptor import okhttp3.OkHttpClient import java.util.concurrent.TimeUnit /** * @author Created by qlang on 2017/7/14. */ class RetrofitClient private constructor(context: Context, baseUrl: String) { var httpCacheDirectory: File? = null val mContext: Context = context var cache: Cache? = null var okHttpClient: OkHttpClient? = null var retrofit: Retrofit? = null val DEFAULT_TIMEOUT: Long = 20 val url = baseUrl init { //快取地址 httpCacheDirectory = httpCacheDirectory ?: File(mContext.cacheDir, "app_cache") try { cache = cache ?: Cache(httpCacheDirectory, 10 * 1024 * 1024) } catch (e: Exception) { Log.e("OKHttp", "Could not create http cache", e) } //okhttp建立了 okHttpClient = OkHttpClient.Builder() .addNetworkInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .cache(cache) .addInterceptor(CacheInterceptor(context)) .addNetworkInterceptor(CacheInterceptor(context)) .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .build() //retrofit建立了 retrofit = Retrofit.Builder() .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(url) .build() } companion object { @Volatile var instance: RetrofitClient? = null var context: Context? = null fun init(context: Context) { this.context = context } fun getInstance(baseUrl: String): RetrofitClient { return instance ?: synchronized(RetrofitClient::class) { if (context == null) throw NullPointerException("context is null.Use init(content) in your Application") RetrofitClient(context!!, baseUrl).also{ instance = it } } } } } fun <T> create(service: Class<T>?): T? { if (service == null) throw RuntimeException("Api service is null!") return retrofit?.create(service) } }
快取輔助類:
CacheInterceptor.kt
import android.content.Context import android.util.Log import com.ql.ufun.utils.NetworkUtils import okhttp3.Interceptor import okhttp3.Response import okhttp3.CacheControl /** * @author Created by qlang on 2017/7/14. */ class CacheInterceptor(context: Context) : Interceptor { val context = context override fun intercept(chain: Interceptor.Chain?): Response? { var request = chain?.request() if (NetworkUtils.isNetConneted(context)) { val response = chain?.proceed(request) // read from cache for 60 s val maxAge = 60 val cacheControl = request?.cacheControl().toString() Log.e("CacheInterceptor", "6s load cahe" + cacheControl) return response?.newBuilder()?.removeHeader("Pragma")?.removeHeader("Cache-Control")?.header("Cache-Control", "public, max-age=" + maxAge)?.build() } else { Log.e("CacheInterceptor", " no network load cahe") request = request?.newBuilder()?.cacheControl(CacheControl.FORCE_CACHE)?.build() val response = chain?.proceed(request) //set cahe times is 3 days val maxStale = 60 * 60 * 24 * 3 return response?.newBuilder()?.removeHeader("Pragma")?.removeHeader("Cache-Control")?.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)?.build() } } }
使用:
1.定義介面
ApiServer.kt
interface ApiServer {
companion object {
val BASE_URL: String get() = "http://route.xxx.com/"
}
@GET("xxxxxx")
fun getHomeTxtData(@Query("xxx") apiid: String, @Query("xxx") sign: String, @Query("currPage") page: String, @Query("maxResult") num: String): Observable<Xxxxx>
2.定義Base Model
BaseModel.kt
import com.ql.xxx.net.ApiServer
import com.ql.xxx.net.RetrofitClient
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
/**
* @author Created by qlang on 2017/7/18.
*/
open class BaseModel {
fun buildServer(): RetrofitClient {
return RetrofitClient.getInstance(ApiServer.BASE_URL)
}
fun <T> Observable<T>.applySchedulers(): Observable<T> {
return subscribeOn(Schedulers.io()).
unsubscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread())
}
}
3.具體的Model
MainModel.kt
/**
* @author Created by qlang on 2017/7/18.
*/
class MainModel : BaseModel() {
fun loadTextData(index: Int): Observable<Xxxxx>? {
val server = buildServer().create(ApiServer::class.java)
return server?.getHomeTxtData(ApiServer.API_ID, ApiServer.API_SIGN, "$index", "20")?.applySchedulers()
}
}
4.發起請求
val model: MainModel by lazy {
MainModel()
}
val observable: Observable<Xxxxx>? = model.loadTextData(index)
observable?.subscribe({ bean: Xxxxx -> listener?.onSuccRespone(bean) },
{ err: Throwable -> listener?.onErrRespone(err) })
附:
基於Glide的圖片載入簡單封裝
ImageLoader.kt
import android.content.Context
import android.graphics.Bitmap
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.animation.GlideAnimation
import com.bumptech.glide.request.target.SimpleTarget
import com.ql.ufun.R
/**
* @author Created by qlang on 2017/7/19.
*/
class ImageLoader {
interface BitmapListener {
fun onCall(bitmap: Bitmap?)
}
companion object {
fun <T : ImageView> loadImg(context: Context, url: String, imageView: T?) {
loadImg(context, url, imageView, R.mipmap.ic_default_img, R.mipmap.ic_default_img)
}
fun <T : ImageView> loadBigImg(context: Context, url: String, imageView: T?) {
if (imageView == null) {
throw IllegalArgumentException("argument error")
}
Glide.with(context).load(url)
.asBitmap()
.format(DecodeFormat.PREFER_ARGB_8888)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.mipmap.ic_default_img)
.error(R.mipmap.ic_default_img)
.into(imageView)
}
fun <T : ImageView> loadImg(context: Context, url: String, imageView: T?, defaultImageResId: Int, errImageResId: Int) {
if (imageView == null) {
throw IllegalArgumentException("argument error")
}
Glide.with(context).load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(defaultImageResId)
.error(errImageResId)
.crossFade().into(imageView)
}
fun loadImg(context: Context, url: String, listener: BitmapListener?) {
Glide.with(context).load(url)
.asBitmap()
.format(DecodeFormat.PREFER_ARGB_8888)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap?, glideAnimation: GlideAnimation<in Bitmap>?) {
listener?.onCall(resource)
}
})
}
}
}