美文网首页
RxNet做网络请求,简洁得没法了

RxNet做网络请求,简洁得没法了

作者: DonaldDu | 来源:发表于2020-08-10 00:06 被阅读0次

RxNet Github

Android里面网络请求一般怎么写?

Kotlin协程

很多人说用Kotlin协程,看了后发现不太好用。

  • 外面需要一个asyncUI {},看着都不爽
  • 如果接口出错了,需要在每个调用处,写逻辑来处理。不能全局处理错误,比如网络超时。
  • 代码不容易懂,比如: deferred1.wait(TOAST)这个wait(TOAST)是什么东西。
  • 没有全局进度框

以下代码引用于 用 Kotlin 协程把网络请求玩出花来

asyncUI {
    // 假设这是两个不同的 api 请求
    val deferred1 = bg {
        Server.getApiStore().login1("173176360", "123456").execute()
    }

    val deferred2 = bg {
        Server.getApiStore().login2("173176360", "123456").execute()
    }

    // 后台请求着 api,此时我还可以在 UI 协程中做我想做的事情
    textView.text = "loading"
    delay(5, TimeUnit.SECONDS)

    // 等 UI 协程中的事情做完了,专心等待 api 请求完成(其实 api 请求有可能已经完成了)
    // 通过提供 ExceptionHandleType 进行异常的过滤
    val response = deferred1.wait(TOAST)
    deferred2.wait(THROUGH) // deferred2 的结果我不关心

    // 此时两个请求肯定都完成了,并且 deferred1 没有异常发生
    textView.text = response.toString()
}

纯OkHttp

  • 代码写起来也比较麻烦,没有提示功能。
  • 不能全局处理错误,比如网络超时。
  • 没有全局进度框
  • 需要切换线程以操作UI
//代码同样来源上面引用的文章
callback = {
    onSuccess =  { res ->
        // TODO
    }

    onFail =  { error -> 
        // TODO
    }
}
request.execute(callback)

封装OkHttp

还有人自己封装OkHttp,这个就看个人了。

我觉得这个不太好用,假如有个接口调用10次,就要写10次接口地址和‘toClass<Response<Student>>()’,显然这样不好。

  • 代码有点冗余(服务地址和返回参对象类)。
  • 不能全局处理错误,比如网络超时(没用过,不太确定有没有)。
  • 没有全局进度框(没用过,不太确定有没有)。

以下代码引用于 RxHttp 2000+star,协程请求,仅需三步

val response = RxHttp.get("/service/...")
    .toClass<Response<Student>>()
    .await()
if (response.code == 200) {
    //拿到data字段(Student)刷新UI
} else {
    //拿到msg字段给出错误提示
} 

干货

那么,有没有一种方法能

  • 全局默认进度框,同时支持自定义进度框。
  • 全局默认处理错误,同时支持自定义处理错误。
  • 多个依次请求也能友好支持。
  • 页面结束,自动取消请求。

有的:RxNet=RxJava3+Retrofit2+OkHttp3

下面就是调用示例。调用返回的对象是接口中申明的类型,有完整的代码提示,IDE中可以看到Hint

    interface API {
        @GET("Simple?net=1&bz=1")
        fun simple(): Observable<ResponsePacket<String>>
    
        @GET("NetError?net=0&bz=1")
        fun netError(): Observable<ResponsePacket<String>>
    
        @GET("BzError?net=1&bz=0")
        fun bzError(): Observable<ResponsePacket<String>>
    
        @GET("authorizeFailed")
        fun authorizeFailed(): Observable<ResponsePacket<String>>
    }

    private fun subscribeX() {
        //简单模式,通常都用这个
        api.simple().subscribeX(context) {
            Toast.makeText(context, "response:" + it.message, Toast.LENGTH_SHORT).show()
        }
        //构造方法模式,看名字就知道功能了
        api.simple().subscribeXBuilder(context)
                .progress {
                    null//null means no default and custom progress
                }.failed {
                    true//return error handled or not
                }.successOnly(true)
                .response {
                    Toast.makeText(context, "response:" + it.message, Toast.LENGTH_SHORT).show()
                }
    }

多个请求依次发起

需要额外引用

implementation "com.github.DonaldDu:XIntent:1.5.3"//Waterfall

    //多个请求依次发起,不调用 next 就自动结束流程。请求间切换时,进度框不会闪烁
    buttonMultReq.setOnClickListener {
        Waterfall.flow {
            apiSample.subscribeX(context) {
                Log.i("TAG", "apiSample1")
                next()//进入下一个flow,可以带任意类型的数据如:next("DATA")
            }
        }.flow {
            apiSample.subscribeX(context) {
                Log.i("TAG", "apiSample2")
                next()
            }
        }.flow {
            apiSample.subscribeX(context) {
                Log.i("TAG", "apiSample3")
                Toast.makeText(context, "response:" + it.message, Toast.LENGTH_SHORT).show()
            }
        }
    }

延时返回结果

有时,想请求慢一点,动画需要时间展示。比如检查App更新,如果太快,屏幕会闪一下,然后显示没有更新的结果。如果延时900ms就可以解决这个问题(个人感觉好些)。

    buttonDelay.setOnClickListener {
        val start = System.currentTimeMillis()
        apiSample.delayResponse(5000)
                .subscribeX(context) {
                    val cost = System.currentTimeMillis() - start
                    Log.i("TAG", "apiSample cost $cost")
                }
    }

实现方式

为了支持默认进度框和全局错误处理需要实现两个类,StyledProgressGenerator 和 IErrorHandler。已经有了默认实现,需要根据实际需要作一些调整就行了。

class SampleStyledProgressGenerator : StyledProgressGenerator {
    override fun generate(observer: IObserverX): StyledProgress? {
        val context = observer.context
        return if (context is FragmentActivity) {
            MultListenerDialog.getInstance(context, observer)
        } else null
    }
}

class SampleErrorHandler : BaseErrorHandler() {
    override fun showDialog(context: Context, msg: String): Dialog? {
        return AlertDialog.Builder(context)
                .setMessage(msg)
                .setPositiveButton("OK", null).show()
    }

    override fun isAuthorizeFailed(activity: Activity, error: IError): Boolean {
        return error.code == 9001
    }

    override fun onLogout(context: Context) {
        val msg = "onLogout"
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
        Log.i(TAG, msg)
    }

    override fun isDebug(): Boolean = true

    companion object {
        private val TAG = IErrorHandler::class.java.simpleName
    }
}

进度框样式调整

默认实现的是这个类MultListenerDialog,可以参考这个自己实现。如果只是调整比较小,也可以直接创建一个同名的Layout(R.layout.net_progress_dialog)自己随意调整就好。

手动控制进度框

如果在接口调用以外的地方需要控制进度框,可以调用以下两个方法。

比如先压缩图片,再上传。在启动压缩前最好显示进度框,上传完成后会自动关闭进度框。还可以实现压缩过程中取消后,就不上传了。

需要特别注意下:如果 Activity中也有同名的方法时,调用以下方法执行的是Activity中定义的,而不是下面的。

fun FragmentActivity.showProgress(): MultListenerDialog {
    val dialog = MultListenerDialog.getInstance(this)
    dialog.showProgress()
    return dialog
}

fun FragmentActivity.dismissProgress(delay: Boolean = true) {
    MultListenerDialog.getInstance(this).dismissProgress(delay)
}

引入依赖

dependencies {
    implementation 'com.github.DonaldDu:RxNet:x.x.x'//JitPack version
}

其它说明

这个项目是由以前的RetrofitRxUtil改名的,主要是以前的名字不太容易看懂功能,所以修改为RxNet,意为用RxJava来快捷实现网络请求的工具。

以前的项目不维护,转到新项目了。

最后

开源不易,写文章更不易,劳烦大家给本文点个赞,可以的话,再给个star,感激不尽

相关文章

  • RxNet做网络请求,简洁得没法了

    RxNet Github Android里面网络请求一般怎么写? Kotlin协程 很多人说用Kotlin协程,看...

  • 全网最简洁的RxNet做网络请求,没有之一

    Android网络请求一般怎么写? Kotlin协程 很多人说用Kotlin协程,看了后发现不太好用。 外面需要一...

  • swift4,网络请求工具Moya

    在OC中,我们使用AFNetworking来进行网络请求,简洁方便。在swift中,我们使用Moya来进行网络请求...

  • Rxjava初见

    Rxjava是什么 它做的工作就是异步,实现了简洁,清晰的异步工作 上面这段代码,描述了发起一个网络请求,同时对U...

  • Retrofit注解的理解

    Retrofit使用注解,使网络请求的代码特别简洁,但是内部是怎样通过注解转换成一个正常格式的网络请求链接的呢?阅...

  • AFet解析

    -(void)loadData{//使用(网络请求类)做网络数据请求NSDictionary *dic=@{@"p...

  • MVP终极抽取(上)

    流程图: 首先创建model 层 并且对他的请求参数,网络请求,数据参数,进行封装,这样可以减小相似代码。更简洁。...

  • NSURLSSion和NSURLConnection

    NSURLConnection系统原生的对网络数据的请求 使用NSURLSession做网络请求 NSURLSes...

  • iOS 一个模块化,接口化的网络请求组件JCNetWokingM

    做iOS开发有一段时间,接触了许多的网络请求组件。但是很多网络请求组件对业务的耦合性比较高,很难脱离业务层。对网络...

  • 项目常见问题(一)

    今天做项目的时候发现了一个奇葩问题, 连续请求了2次网络,连续请求网络可能造成很多问题, 浪费流量, 数据不同步,...

网友评论

      本文标题:RxNet做网络请求,简洁得没法了

      本文链接:https://www.haomeiwen.com/subject/fifddktx.html