定义网络仓库,封装网络接口
/** * MVVM架构网络仓库 * UI->ViewModel->Repository->LiveData(ViewModel)->UI */ class NetworkRepository private constructor() { companion object { val instance = NetworkRepository.holder } private object NetworkRepository { val holder = NetworkRepository() } inline fun <reified T> wrapHttpCallback(): MvvmHttpCallback<T> { return object : MvvmHttpCallback<T>() { } } inline fun <reified T> newCallback(liveData: MutableLiveData<TKState<T>>): HttpCallback<TKResponse<T>> { val type = wrapHttpCallback<T>().getType() return object : HttpCallback<TKResponse<T>>(type) { override fun onStart() { liveData.value = TKState.start() } override fun onNext(response: TKResponse<T>?) { liveData.value = TKState.response(response) } override fun onError(e: Throwable?) { liveData.value = TKState.error(e) } override fun onComplete() { /** * 亲,此处不要做任何操作,不要给LiveData赋值,防止onNext对应的LiveData数据被覆盖, * 在TKState类handle方法里会特别处理回调的,放心好了 */ } override fun onProgress(readBytes: Long, totalBytes: Long) { liveData.value = TKState.progress(readBytes, totalBytes) } } } inline fun <reified T> httpGet( context: Context, url: String, params: Map<String, Any?>?, tag: Any? = null ): MutableLiveData<TKState<T>> { val liveData = MutableLiveData<TKState<T>>() RxHttp.getInstance() .get(context) .url(url) .params(params) .tag(tag) .enqueue(newCallback(liveData)) return liveData } inline fun <reified T> httpPost( context: Context, url: String, params: Map<String, Any?>?, tag: Any? = null ): MutableLiveData<TKState<T>> { val liveData = MutableLiveData<TKState<T>>() RxHttp.getInstance().post(context) .url(url) .params(params) .tag(tag) .enqueue(newCallback(liveData)) return liveData } inline fun <reified T> httpPostForm( context: Context, url: String, params: Map<String, Any?>?, tag: Any? = null ): MutableLiveData<TKState<T>> { val liveData = MutableLiveData<TKState<T>>() RxHttp.getInstance().postForm(context) .url(url) .params(params) .tag(tag) .enqueue(newCallback(liveData)) return liveData } inline fun <reified T> httpPut( context: Context, url: String, params: Map<String, Any?>?, tag: Any? = null ): MutableLiveData<TKState<T>> { val liveData = MutableLiveData<TKState<T>>() RxHttp.getInstance().put(context) .url(url) .params(params) .tag(tag) .enqueue(newCallback(liveData)) return liveData } inline fun <reified T> httpDelete( context: Context, url: String, params: Map<String, Any?>?, tag: Any? = null ): MutableLiveData<TKState<T>> { val liveData = MutableLiveData<TKState<T>>() RxHttp.getInstance().delete(context) .params(params) .url(url) .tag(tag) .enqueue(newCallback(liveData)) return liveData } /** *上传 *支持上传多个文件,map中对应的value类型为File类型或Uri类型 *支持监听上传进度 val map =Map<String,Any>() map.put("model", "xiaomi") map.put("os", "android") map.put("avatar",File("xxx")) map.put("video",uri) */ inline fun <reified T> httpUpload( context: Context, url: String, params: Map<String, Any?>?, tag: Any? = null ): MutableLiveData<TKState<T>> { val liveData = MutableLiveData<TKState<T>>() RxHttp.getInstance().upload(context) .url(url) .params(params) .tag(tag) .enqueue(newCallback(liveData)) return liveData } /** * 下载 * context:上下文,如不需要和生命周期绑定,应该传递applicationContext * url:下载地址 * dir:本地目录路径 * filename:保存文件名称 * callback:下载进度回调 * md5:下载文件的MD5值 * breakpoint:是否支持断点下载,默认为true */ fun httpDownload(context: Context, url: String, dir: String, filename: String, callback: DownloadCallback, md5: String? = null, breakPoint: Boolean = true, tag: Any? = null) { RxHttp.getInstance().download(context).dir(dir).filename(filename).breakpoint(breakPoint).md5(md5).url(url).tag(tag).enqueue(callback) } }定义TKState类,用于将网络回调转化为LiveData
/** *将HttpCallback回调转化为对应的LiveData */ class TKState<T> { var state: Int = 0 var code = TKErrorCode.ERRCODE_UNKNOWN var msg: String? = null var data: T? = null var progress: Long = 0 var total: Long = 0 @JvmOverloads constructor(state: Int, data: T? = null, msg: String? = "") { this.state = state this.data = data this.msg = msg } constructor(state: Int, throwable: Throwable?) { this.state = state handleThrowable(throwable).run { this@TKState.code = first this@TKState.msg = second } } constructor(state: Int, progress: Long, total: Long) { this.state = state this.progress = progress this.total = total } fun handle(handleCallback: HandleCallback<T>.() -> Unit) { val callback = HandleCallback<T>() callback.apply(handleCallback) when (state) { START -> { callback.onStart?.invoke() } SUCCESS -> { callback.onSuccess?.invoke(data) } FAIL -> { callback.onFailure?.invoke(code, msg) } PROGRESS -> { callback.onProgress?.invoke(progress, total) } } if (state == SUCCESS || state == FAIL) { callback.onComplete?.invoke() } } open class HandleCallback<T> { var onStart: (() -> Unit)? = null var onSuccess: ((T?) -> Unit)? = null var onFailure: ((Int, String?) -> Unit)? = null var onComplete: (() -> Unit)? = null var onProgress: ((Long, Long) -> Unit)? = null fun onStart(callback: (() -> Unit)?) { this.onStart = callback } fun onSuccess(callback: ((T?) -> Unit)?) { this.onSuccess = callback } fun onFailure(callback: ((Int, String?) -> Unit)?) { this.onFailure = callback } fun onComplete(callback: (() -> Unit)?) { this.onComplete = callback } fun onProgress(callback: ((Long, Long) -> Unit)?) { this.onProgress = callback } } companion object { const val START = 0 const val SUCCESS = 1 const val FAIL = 2 const val PROGRESS = 3 fun <T> start(): TKState<T> { return TKState(START) } fun <T> response(response: TKResponse<T>?): TKState<T> { if (response != null) { if (response.isSuccess()) { return TKState(SUCCESS, response.data, null) } else { return error(ServerException(response.code, response.msg)) } } else { return error(NullResponseException(TKErrorCode.ERRCODE_RESPONSE_NULL, TKErrorCode.ERRCODE_RESPONSE_NULL_DESC)) } } fun <T> error(t: Throwable?): TKState<T> { return TKState(FAIL, t) } fun <T> progress(progress: Long, total: Long): TKState<T> { return TKState(PROGRESS, progress, total) } } }