Android Kotlin学习(三)- Retrofit

本文介绍了如何在Kotlin中使用单例模式实现Retrofit网络库的封装,包括设置拦截器处理Cookie,以及泛型在数据模型中的应用。同时,文章还展示了MMKV本地存储的简单封装,用于保存和读取数据。最后,给出了一个使用封装后的Retrofit进行API接口调用的登录示例。
摘要由CSDN通过智能技术生成

单例模式

kotlin单例模式实现方式有多种,最简单的直接使用Object,这里使用带有线程安全的方式:

class SingletonDemo private constructor() {
    companion object {
        val instance: SingletonDemo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
        SingletonDemo() }
    }
}

泛型

Kotlin 的泛型也允许在定义类、接口、函数时使用泛型形参,这个泛型形参将在声明变量、创建对象、调用方法时动态地指定

data class BaseResponse<T>(var data:T, var errorCode:Int, var errorMsg:String)

Retrofit封装

import com.kotlin.demo.common.Constant
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.*
import java.util.concurrent.TimeUnit


class RetrofitUtil {
    val BASE_URL = "https://www.wanandroid.com";
    var retrofit:Retrofit ?= null;
    companion object{
        val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
            RetrofitUtil();
        }
    }
    init {
        create();
    }
    class ReceivedCookiesInterceptor : Interceptor{
        override fun intercept(chain: Interceptor.Chain): Response {
            var originalResponse = chain.proceed(chain.request());
            //这里获取请求返回的cookie
            //这里获取请求返回的cookie
            if (!originalResponse.headers("Set-Cookie").isEmpty()) {
                val cookies: MutableSet<String> = HashSet<String>()
                for (header in originalResponse.headers("Set-Cookie")) {
                    cookies.add(header)
                }
                MmkvUtil.encodeSet(Constant.MMKV_COOKIE_KEY, cookies)
            }

            return originalResponse;
        }
    }
    class AddCookiesInterceptor : Interceptor {
        override fun intercept(chain: Interceptor.Chain): Response {
            var builder = chain.request().newBuilder();
            val cookie: Set<String> = MmkvUtil.decodeStringSet(Constant.MMKV_COOKIE_KEY);
            if (cookie != null) {
                for (c in cookie) {
                    builder.addHeader("Cookie", c)
                }
            }
            return chain.proceed(builder.build());
        }
    }
    fun create():Retrofit?{
        var  builder = OkHttpClient.Builder();
        var httpLoggingInterceptor = HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        var client = builder.addInterceptor(httpLoggingInterceptor)
            .addInterceptor(ReceivedCookiesInterceptor())
            .addInterceptor(AddCookiesInterceptor())
            .readTimeout(10, TimeUnit.SECONDS)
            .connectTimeout(10, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true).build();
        retrofit = Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).client(client).build();
        return retrofit;
    }
}

MMKV封装(来源网络)

从网上直接找了个MMKV封装的工具类

import android.os.Parcelable
import com.tencent.mmkv.MMKV


object  MmkvUtil{

    var mv: MMKV? = null
    init {
        mv=MMKV.defaultMMKV()
    }

    fun encode(key: String?, `object`: Any) {
        when (`object`) {
            is String -> {
                mv?.encode(key, `object`)
            }
            is Int -> {
                mv?.encode(key, `object`)
            }
            is Boolean -> {
                mv?.encode(key, `object`)
            }
            is Float -> {
                mv?.encode(key, `object`)
            }
            is Long -> {
                mv?.encode(key, `object`)
            }
            is Double -> {
                mv?.encode(key, `object`)
            }
            is ByteArray -> {
                mv?.encode(key, `object`)
            }
            else -> {
                mv?.encode(key, `object`.toString())
            }
        }
    }

    fun encodeSet(key: String?, sets: Set<String?>?) {
        mv?.encode(key, sets)
    }

    fun encodeParcelable(key: String?, obj: Parcelable?) {
        mv?.encode(key, obj)
    }


    fun decodeInt(key: String?): Int? {
        return mv?.decodeInt(key, 0)
    }

    fun decodeDouble(key: String?): Double {
        return mv?.decodeDouble(key, 0.00)!!
    }

    fun decodeLong(key: String?): Long {
        return mv?.decodeLong(key, 0L)!!
    }

    fun decodeBoolean(key: String?): Boolean {
        return mv?.decodeBool(key, false) == true
    }

    fun decodeBooleanTure(key: String?, defaultValue: Boolean): Boolean {
        return mv?.decodeBool(key, defaultValue) == true
    }

    fun decodeFloat(key: String?): Float {
        return mv?.decodeFloat(key, 0f)!!
    }

    fun decodeBytes(key: String?): ByteArray {
        return mv?.decodeBytes(key)!!
    }

    fun decodeString(key: String?): String {
        return mv?.decodeString(key, "").toString()
    }

    fun decodeStringDef(key: String?, defaultValue: String): String {
        return mv?.decodeString(key, defaultValue).toString()
    }


    fun decodeStringSet(key: String?): Set<String> {
        return mv?.decodeStringSet(key, emptySet()) as Set<String>
    }

    fun <T : Parcelable?> decodeParcelable(key: String?, tClass: Class<T>?): T? {
        return mv?.decodeParcelable(key, tClass)
    }

moveKey(key: String?) {
mv?.removeValueForKey(key)
}

    fun clearAll() {
        mv?.clearAll()
    }

}

API接口

import com.kotlin.demo.model.user.LoginResponse
import retrofit2.Call
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.POST

interface UserRequest {
    @FormUrlEncoded
    @POST("user/login")
    fun login(
        @Field("username") username: String?,
        @Field("password") password: String?
    ): Call<BaseResponse<LoginResponse>>
}

使用实例

open class LoginViewModel() : ViewModel() {
    var TAG = "LoginViewModel";
    var userLd : MutableLiveData<User> = MutableLiveData<User>();
    lateinit var request:UserRequest;
    init {
        request = RetrofitUtil.instance.retrofit?.create(UserRequest::class.java)!!;
    }
    fun onLogin(v:View){
        Log.i(TAG,"login ${userLd.value?.name} ${userLd.value?.pwd}");
        var call = request.login(userLd.value?.name,userLd.value?.pwd);
        call.enqueue(object:Callback<BaseResponse<LoginResponse>>{
            override fun onResponse(
                call: Call<BaseResponse<LoginResponse>>,
                response: Response<BaseResponse<LoginResponse>>
            ) {
                Log.i(TAG,"onResponse = "+ (response.body()?.errorCode ?: -10000));
            }
            override fun onFailure(call: Call<BaseResponse<LoginResponse>>, t: Throwable) {
            }
        })
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值