简易MVVM网络请求框架(基于Kotlin实现)
使用kotlin以最少代码实现retrofit+okhttp的网络请求
retrofit+okhttp的初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| object ApiClient { private val okHttpClient: OkHttpClient private val retrofit: Retrofit
init { val logger = HttpLoggingInterceptor() if (BuildConfig.DEBUG) { logger.level = HttpLoggingInterceptor.Level.BODY } else { logger.level = HttpLoggingInterceptor.Level.NONE } val cache = Cache(NicebuyApp.app.cacheDir, 10 * 1024 * 1024) okHttpClient = OkHttpClient.Builder().run { readTimeout(30, TimeUnit.SECONDS) writeTimeout(60, TimeUnit.SECONDS) addInterceptor(logger) cache(cache) build() } val gson = GsonBuilder() .setLenient() .create() retrofit = Retrofit.Builder().run { baseUrl("https://www.nicebuy.io") addConverterFactory(GsonConverterFactory.create(gson)) client(okHttpClient) build() } } fun getRetrofit(): Retrofit { return retrofit }
fun getOkHttpClient(): OkHttpClient { return okHttpClient } }
|
接口service定义
1 2 3 4
| interface TestService { @GET("/v1/user/info") suspend fun getUserInfo(@Query("uid") uid: String): ApiResponse<UserInfo> }
|
定义一个顶层函数callFromNet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| suspend fun <T> callFromNet(apiFunc: suspend () -> ApiResponse<T>): Resource<T> { return try { val result = apiFunc.invoke() if (result.code == 0) { Resource.success(result.data, result.code, result.status) } else { Resource.error(null, result.code, result.status) } } catch (error: HttpException) { if (BuildConfig.DEBUG) error.printStackTrace() handleError(error) } catch (throwable: Throwable) { if (BuildConfig.DEBUG) throwable.printStackTrace() Resource.error(null, 0, throwable.message ?: throwable.toString()) } }
private fun <T> handleError(error: HttpException): Resource<T> { return Resource.error(null, error.code(), error.message()) }
|
Repo的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class TestRepo(val context: CoroutineContext) { private val service: TestService = ApiClient.getRetrofit().create()
fun getUserInfo(uid: String): LiveData<Resource<UserInfo>> { return liveData(context) { emit(Resource.loading(null)) val resource = callFromNet { service.getUserInfo() } emit(resource) } } }
|
ViewModel实现
1 2 3 4 5 6 7 8 9 10 11
| class TestViewModel : ViewModel() { private val testRepo = TestRepo(viewModelScope.coroutineContext) private val _uidData = MutableLiveData<String>() val userInfoData = _uidData.switchMap { testRepo.getUserInfo(it) }
fun setUserId(uid: String) { _uidData.value = uid } }
|
那么activity里面的使用就很简单了
1 2 3 4 5 6 7 8 9 10 11 12
| private val testViewModel : TestViewModel by viewModels()
private fun getUserInfo(uid: String) { testViewModel.userInfoData.observe(this, Observer { when (it.status) { Status.SUCCESS -> TODO() Status.ERROR -> TODO() Status.LOADING -> TODO() } }) testViewModel.setUserId(uid) }
|