RxHttp - 輕量級(jí)宪睹、可擴(kuò)展、易使用蚕钦、完美兼容MVVM亭病、MVC架構(gòu)的網(wǎng)絡(luò)封裝類庫(kù)

前言

RxHttp是基于RxJava2+Retrofit 2.9.0+OkHttp 4.9.0實(shí)現(xiàn)的輕量級(jí),完美兼容MVVM架構(gòu)的網(wǎng)絡(luò)請(qǐng)求封裝類庫(kù)嘶居,小巧精致罪帖,簡(jiǎn)單易用促煮,輕輕松松搞定網(wǎng)絡(luò)請(qǐng)求。

GitHub

https://github.com/kongpf8848/RxHttp

亮點(diǎn)

  • 代碼量極少整袁,類庫(kù)大小不足100kb菠齿,但足以勝任大部分APP的網(wǎng)絡(luò)請(qǐng)求任務(wù),濃縮的都是精華啊^

  • 完美兼容MVVM坐昙,MVC架構(gòu)绳匀,兼容Kotlin和Java,Kotlin+MVVM+RxHttp組合使用更酸爽炸客,MVVM官方推薦疾棵,抱緊Google大腿就對(duì)了

  • 完美解決泛型類型擦除的棘手問(wèn)題,還原泛型的真實(shí)類型

  • 天生支持網(wǎng)絡(luò)請(qǐng)求和Activity痹仙,F(xiàn)ragment生命周期綁定是尔,界面銷毀時(shí)自動(dòng)取消網(wǎng)絡(luò)請(qǐng)求回調(diào)

  • 天生支持多BaseUrl,支持動(dòng)態(tài)傳入U(xiǎn)rl

  • 支持自定義OkHttpClient.Builder开仰,可高度自定義網(wǎng)絡(luò)請(qǐng)求參數(shù)

  • 支持Glide等和網(wǎng)絡(luò)請(qǐng)求公用一個(gè)OkHttpClient拟枚,充分利用OkHttpClient的線程池和連接池,大部分情況下一個(gè)App一個(gè)OkHttpClient就夠了

  • 支持GET众弓,POST恩溅,PUT,DELETE等請(qǐng)求方式田轧,支持文件上傳及進(jìn)度監(jiān)聽(tīng)暴匠,支持同時(shí)上傳多個(gè)文件鞍恢,支持Uri上傳

  • 支持文件下載及進(jìn)度監(jiān)聽(tīng)傻粘,支持大文件下載,支持?jǐn)帱c(diǎn)下載

使用要求

項(xiàng)目基于AndroidX帮掉,Java8+弦悉,minSdkVersion>=21

使用

implementation 'com.github.kongpf8848:RxHttp:1.0.11'

配置(可選)

  RxHttpConfig.getInstance()
    /**
     * 失敗重試次數(shù)
     */
    .maxRetries(3)
    /**
     * 每次失敗重試間隔時(shí)間
     */
    .retryDelayMillis(200)
    /**
     * 自定義OkHttpClient.Builder(),RxHttp支持自定義OkHttpClient.Builder()蟆炊,
     * 如不定義稽莉,則使用RxHttp默認(rèn)的OkHttpClient.Builder()
     */
    .builder(OkHttpClient.Builder().apply {
        connectTimeout(60, TimeUnit.SECONDS)
        readTimeout(60, TimeUnit.SECONDS)
        writeTimeout(60, TimeUnit.SECONDS)
        /**
         * DEBUG模式下,添加日志攔截器涩搓,建議使用RxHttp中的FixHttpLoggingInterceptor污秆,使用OkHttp的HttpLoggingInterceptor在上傳下載的時(shí)候會(huì)有IOException問(wèn)題
         */
        if (BuildConfig.DEBUG) {
            addInterceptor(FixHttpLoggingInterceptor().apply {
                level = FixHttpLoggingInterceptor.Level.BODY
            })
        }
    })

基礎(chǔ)使用

  • GET/POST/PUT/DELETE/上傳請(qǐng)求
   RxHttp.getInstance()
    /**
     * get:請(qǐng)求類型,可為get,post,put,delete,upload昧甘,分別對(duì)應(yīng)GET/POST/PUT/DELETE/上傳請(qǐng)求
     * context:上下文良拼,可為Context,Activity或Fragment類型充边,當(dāng)context為Activity或Fragment時(shí)網(wǎng)絡(luò)請(qǐng)求和生命周期綁定
     */
    .get(context)
    /**
     * 請(qǐng)求url庸推,如https://www.baidu.com
     */
    .url("xxx")
    /**
     *請(qǐng)求參數(shù)鍵值對(duì),類型為Map<String, Any?>?,如hashMapOf("name" to "jack")
     */
    .params(map)
    /**
     *每個(gè)網(wǎng)絡(luò)請(qǐng)求對(duì)應(yīng)的tag值贬媒,可為null聋亡,用于后續(xù)手動(dòng)根據(jù)tag取消指定網(wǎng)絡(luò)請(qǐng)求
     */
    .tag("xxx")
    /**
     * HttpCallback:網(wǎng)絡(luò)回調(diào),參數(shù)xxx為返回?cái)?shù)據(jù)對(duì)應(yīng)的數(shù)據(jù)模型际乘,
     * 類似RxJava中的Observer坡倔,onComplete只有在onNext回調(diào)之后執(zhí)行,如發(fā)生錯(cuò)誤則只會(huì)回調(diào)onError而不會(huì)執(zhí)行onComplete
     */
    .enqueue(object : HttpCallback<xxx>() {
        /**
         * http請(qǐng)求開(kāi)始時(shí)回調(diào)
         */
        override fun onStart() {

        }

        /**
         * http請(qǐng)求成功時(shí)回調(diào)
         */
        override fun onNext(response: xxx?) {

        }

        /**
         * http請(qǐng)求失敗時(shí)回調(diào)
         */
        override fun onError(e: Throwable?) {

        }

        /**
         * http請(qǐng)求成功完成時(shí)回調(diào)
         */
        override fun onComplete() {

        }

        /**
         * 上傳進(jìn)度回調(diào),請(qǐng)求類型為upload時(shí)才會(huì)回調(diào)
         */
        override fun onProgress(readBytes: Long, totalBytes: Long) {
        
        }
    })
  • 下載請(qǐng)求
   RxHttp.getInstance()
      /**
       * download:請(qǐng)求類型蚓庭,下載請(qǐng)求
       * context:上下文致讥,如不需要和生命周期綁定,應(yīng)該傳遞applicationContext
       */
      .download(context)
      /**
       * 保存路徑
       */
      .dir(dir)
      /**
       *保存文件名稱
       */
      .filename(filename)
      /**
       * 是否為斷點(diǎn)下載,默認(rèn)為false
       */
      .breakpoint(true)
      /**
       * 下載地址器赞,如http://study.163.com/pub/ucmooc/ucmooc-android-official.apk
       */
      .url(url)
      /**
       * 請(qǐng)求Tag
       */
      .tag(null)
      /**
       * 下載回調(diào)
       */
      .enqueue(object: DownloadCallback() {
          /**
           * 下載開(kāi)始時(shí)回調(diào)
           */
          override fun onStart() {
    
          }
    
          /**
           * 下載完成時(shí)回調(diào)
           */
          override fun onNext(response: DownloadInfo?) {
    
          }
    
          /**
           * 下載失敗時(shí)回調(diào)
           */
          override fun onError(e: Throwable?) {
    
          }
    
          /**
           * 下載完成之后回調(diào)
           */
          override fun onComplete() {
    
          }
    
          /**
           * 下載進(jìn)度回調(diào)
           */
          override fun onProgress(readBytes: Long, totalBytes: Long) {
    
          }
    
      })

  • 取消請(qǐng)求
    /**
     * tag:Any?,請(qǐng)求Tag,對(duì)應(yīng)網(wǎng)絡(luò)請(qǐng)求里的Tag值
     * 如不為null,則取消指定網(wǎng)絡(luò)請(qǐng)求,
     * 如為null垢袱,則取消所有網(wǎng)絡(luò)請(qǐng)求
     */
    RxHttp.getInstance().cancelRequest(tag)

項(xiàng)目實(shí)戰(zhàn)

此處假設(shè)服務(wù)端返回的數(shù)據(jù)格式為{"code":xxx,"data":T,"msg":""},其中code為響應(yīng)碼港柜,整型请契,等于200時(shí)為成功,其余為失敗夏醉,data對(duì)應(yīng)的數(shù)據(jù)類型為泛型(boolean爽锥,int,double畔柔,String氯夷,對(duì)象{ },數(shù)組[ ]等類型)

{
   "code": 200,
   "data":T,
   "msg": ""
}

對(duì)應(yīng)的Response類為

class TKResponse<T>(val code:Int,val msg: String?, val data: T?) : Serializable {
    companion object{
        const val STATUS_OK=200
    }
    fun isSuccess():Boolean{
        return code== STATUS_OK
    }
}
  • MVC項(xiàng)目

    • 定義MVCHttpCallback,用于將網(wǎng)絡(luò)請(qǐng)求結(jié)果回調(diào)給UI界面
    abstract class MVCHttpCallback<T> {
    
        private val type: Type
    
        init {
            val arg = TypeUtil.getType(javaClass)
            type = TypeBuilder
                    .newInstance(TKResponse::class.java)
                    .addTypeParam(arg)
                    .build()
        }
    
        fun getType(): Type {
            return this.type
        }
    
        /**
         * 請(qǐng)求開(kāi)始時(shí)回調(diào)靶擦,可以在此加載loading對(duì)話框等,默認(rèn)為空實(shí)現(xiàn)
         */
        open fun onStart() {}
       
        /**
         * 抽象方法腮考,請(qǐng)求成功回調(diào),返回內(nèi)容為泛型玄捕,對(duì)應(yīng)TKResponse的data
         */
        abstract fun onSuccess(result: T?)
    
        /**
         * 抽象方法踩蔚,請(qǐng)求失敗回調(diào),返回內(nèi)容為code(錯(cuò)誤碼)枚粘,msg(錯(cuò)誤信息)
         */
        abstract fun onFailure(code: Int, msg: String?)
    
        /**
         * 上傳進(jìn)度回調(diào)馅闽,默認(rèn)為空實(shí)現(xiàn)
         */
        open fun onProgress(readBytes: Long, totalBytes: Long) {}
    
        /**
         * 請(qǐng)求完成時(shí)回調(diào),請(qǐng)求成功之后才會(huì)回調(diào)此方法馍迄,默認(rèn)為空實(shí)現(xiàn)
         */
        open fun onComplete() {}
    
    }
    
    • 定義網(wǎng)絡(luò)接口,封裝GET/POST等網(wǎng)絡(luò)請(qǐng)求
    object MVCApi {
    
        /**
         * GET請(qǐng)求
         * context:上下文
         * url:請(qǐng)求url
         * params:參數(shù)列表福也,可為null
         * tag:標(biāo)識(shí)一個(gè)網(wǎng)絡(luò)請(qǐng)求
         * callback:網(wǎng)絡(luò)請(qǐng)求回調(diào)
         */
        inline fun <reified T> httpGet(
                context: Context,
                url: String,
                params: Map<String, Any?>?,
                tag: Any? = null,
                callback: MVCHttpCallback<T>
        ) {
            RxHttp.getInstance().get(context)
                    .url(url)
                    .params(params)
                    .tag(tag)
                    .enqueue(simpleHttpCallback(callback))
        }
    
        /**
         * POST請(qǐng)求
         * context:上下文
         * url:請(qǐng)求url
         * params:參數(shù)列表,可為null
         * tag:標(biāo)識(shí)一個(gè)網(wǎng)絡(luò)請(qǐng)求
         * callback:網(wǎng)絡(luò)請(qǐng)求回調(diào)
         */
        inline fun <reified T> httpPost(
                context: Context,
                url: String,
                params: Map<String, Any?>?,
                tag: Any? = null,
                callback: MVCHttpCallback<T>
        ) {
            RxHttp.getInstance().post(context)
                    .url(url)
                    .params(params)
                    .tag(tag)
                    .enqueue(simpleHttpCallback(callback))
        }
        
        ......
        
         inline fun <reified T> simpleHttpCallback(callback: MVCHttpCallback<T>): HttpCallback<TKResponse<T>> {
            return object : HttpCallback<TKResponse<T>>(callback.getType()) {
                override fun onStart() {
                    super.onStart()
                    callback.onStart()
                }
    
                override fun onNext(response: TKResponse<T>?) {
                    if (response != null) {
                        if (response.isSuccess()) {
                            callback.onSuccess(response.data)
                        } else {
                            return onError(ServerException(response.code, response.msg))
                        }
    
                    } else {
                        return onError(NullResponseException(TKErrorCode.ERRCODE_RESPONSE_NULL, TKErrorCode.ERRCODE_RESPONSE_NULL_DESC))
                    }
    
                }
    
                override fun onError(e: Throwable?) {
                    handleThrowable(e).run {
                        callback.onFailure(first, second)
                    }
                }
    
                override fun onComplete() {
                    super.onComplete()
                    callback.onComplete()
                }
    
                override fun onProgress(readBytes: Long, totalBytes: Long) {
                    super.onProgress(readBytes, totalBytes)
                    callback.onProgress(readBytes, totalBytes)
                }
            }
        }
    
    • 在View層如Activity中調(diào)用網(wǎng)絡(luò)接口
    MVCApi.httpGet(
        context = baseActivity,
        url = TKURL.URL_GET,
        params = null,
        tag = null, 
        callback = object : MVCHttpCallback<List<Banner>>() {
        override fun onStart() {
            LogUtils.d(TAG, "onButtonGet onStart() called")
        }
    
        override fun onSuccess(result: List<Banner>?) {
            Log.d(TAG, "onButtonGet onSuccess() called with: result = $result")
        }
    
        override fun onFailure(code: Int, msg: String?) {
            Log.d(TAG, "onButtonGet onFailure() called with: code = $code, msg = $msg")
        }
    
        override fun onComplete() {
            Log.d(TAG, "onButtonGet onComplete() called")
        }
    
    })
    

    具體使用可以參考demo代碼攀圈,demo中有詳細(xì)的示例演示MVC項(xiàng)目如何使用RxHttp

  • MVVM項(xiàng)目

    • 定義Activity基類BaseMvvmActivity
    abstract class BaseMvvmActivity<VM : BaseViewModel, VDB : ViewDataBinding> : AppCompatActivity(){
    
       lateinit var viewModel: VM
       lateinit var binding: VDB
    
       protected abstract fun getLayoutId(): Int
    
       final override fun onCreate(savedInstanceState: Bundle?) {
           onCreateStart(savedInstanceState)
           super.onCreate(savedInstanceState)
           binding = DataBindingUtil.setContentView(this, getLayoutId())
           binding.lifecycleOwner = this
           createViewModel()
           onCreateEnd(savedInstanceState)
       }
    
       protected open fun onCreateStart(savedInstanceState: Bundle?) {}
       protected open fun onCreateEnd(savedInstanceState: Bundle?) {}
    
       /**
        * 創(chuàng)建ViewModel
        */
       private fun createViewModel() {
           val type = findType(javaClass.genericSuperclass)
           val modelClass = if (type is ParameterizedType) {
               type.actualTypeArguments[0] as Class<VM>
           } else {
               BaseViewModel::class.java as Class<VM>
           }
           viewModel = ViewModelProvider(this).get(modelClass)
       }
    
       private fun findType(type: Type): Type?{
           return when(type){
               is ParameterizedType -> type
               is Class<*> ->{
               findType(type.genericSuperclass)
               }
               else ->{
               null
               }
           }
       }
    
    }
    
    • 定義ViewModel的基類BaseViewModel
    open class BaseViewModel(application: Application) : AndroidViewModel(application) {
    
       /**
        * 網(wǎng)絡(luò)倉(cāng)庫(kù)
        */
       protected val networkbaseRepository: NetworkRepository = NetworkRepository.instance
       
       /**
        * 上下文
        */
       protected var context: Context = application.applicationContext
    
    }
    
    • 定義網(wǎng)絡(luò)倉(cāng)庫(kù)暴凑,封裝網(wǎng)絡(luò)接口
    /**
    * MVVM架構(gòu)網(wǎng)絡(luò)倉(cāng)庫(kù)
    * 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對(duì)應(yīng)的LiveData數(shù)據(jù)被覆蓋,
                * 在TKState類handle方法里會(huì)特別處理回調(diào)的量承,放心好了
                */
               }
    
               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
       }
    
    
       /**
        *上傳
        *支持上傳多個(gè)文件,map中對(duì)應(yīng)的value類型為File類型或Uri類型
        *支持監(jiān)聽(tīng)上傳進(jìn)度
           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:上下文,如不需要和生命周期綁定,應(yīng)該傳遞applicationContext
        * url:下載地址
        * dir:本地目錄路徑
        * filename:保存文件名稱
        * callback:下載進(jìn)度回調(diào)
        * md5:下載文件的MD5值
        * breakpoint:是否支持?jǐn)帱c(diǎn)下載,默認(rèn)為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類搬设,用于將網(wǎng)絡(luò)回調(diào)轉(zhuǎn)化為L(zhǎng)iveData
    /**
     *將HttpCallback回調(diào)轉(zhuǎn)化為對(duì)應(yīng)的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)
           }
       }
    
    }
    
    • 經(jīng)過(guò)一系列封裝穴店,最后在View層如Activity中ViewModel調(diào)用Repository中的接口
     viewModel.testPost(hashMapOf(
               "name" to "jack",
               "location" to "shanghai",
               "age" to 28)
       )
       .observeState(this) {
           onStart {
             LogUtils.d(TAG, "onButtonPost() onStart called")
           }
           onSuccess {
             LogUtils.d(TAG, "onButtonPost() onSuccess called:${it}")
           }
           onFailure { code, msg ->
             ToastHelper.toast("onButtonPost() onFailure,code:${code},msg:${msg}")
           }
           onComplete {
             LogUtils.d(TAG, "onButtonPost() onComplete called")
           }
       }
    

    具體使用還要參考demo代碼,demo中有詳細(xì)的示例演示MVVM項(xiàng)目如何使用RxHttp

強(qiáng)烈建議下載Demo代碼拿穴,Demo中有詳細(xì)的示例泣洞,演示MVVM及MVC架構(gòu)如何使用RxHttp,如果本文對(duì)你有幫助默色,可以考慮給我點(diǎn)贊哦

Demo

https://github.com/kongpf8848/RxHttp

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末球凰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子腿宰,更是在濱河造成了極大的恐慌呕诉,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吃度,死亡現(xiàn)場(chǎng)離奇詭異甩挫,居然都是意外死亡顷编,警方通過(guò)查閱死者的電腦和手機(jī)瞎饲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)连霉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)散庶,“玉大人,你說(shuō)我怎么就攤上這事歉胶∮直” “怎么了智末?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵汁尺,是天一觀的道長(zhǎng)法精。 經(jīng)常有香客問(wèn)我,道長(zhǎng)痴突,這世上最難降的妖魔是什么搂蜓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮苞也,結(jié)果婚禮上洛勉,老公的妹妹穿的比我還像新娘粘秆。我一直安慰自己如迟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布攻走。 她就那樣靜靜地躺著殷勘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昔搂。 梳的紋絲不亂的頭發(fā)上玲销,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音摘符,去河邊找鬼贤斜。 笑死策吠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瘩绒。 我是一名探鬼主播猴抹,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼锁荔!你這毒婦竟也來(lái)了蟀给?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤阳堕,失蹤者是張志新(化名)和其女友劉穎跋理,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體恬总,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡前普,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了壹堰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汁政。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖缀旁,靈堂內(nèi)的尸體忽然破棺而出记劈,到底是詐尸還是另有隱情,我是刑警寧澤并巍,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布目木,位于F島的核電站,受9級(jí)特大地震影響懊渡,放射性物質(zhì)發(fā)生泄漏刽射。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一剃执、第九天 我趴在偏房一處隱蔽的房頂上張望誓禁。 院中可真熱鬧,春花似錦肾档、人聲如沸摹恰。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)俗慈。三九已至,卻和暖如春遣耍,著一層夾襖步出監(jiān)牢的瞬間闺阱,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工舵变, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留酣溃,地道東北人瘦穆。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像赊豌,于是被迫代替她去往敵國(guó)和親难审。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350