preface

I haven’t written a blog for a long time, and I have been busy recently. Just changed the job, just a month into the job, alas, the weekend has to go home, has no time to write blog, today finally take time to send out this blog.

About network requests. All you know about them is okHTTP, RetroFIT2 and other big companies. Use it smoothly, many people including the author will add a layer of encapsulation in their own. Mainly for the convenience of use in their own projects.

Kotlin has been out for a long time. I believe you are familiar with it. What I bring today is a network request framework encapsulated by coroutine + Retrofit.

Based on using

People are short tempered these days. Let me show you what a GET request looks like. The first is configuration. Here I use DSL style to configure basic information and so on. It’s also convenient.

private val moya by lazy {
    moya(this) {
        url = "https://www.wanandroid.com"
        retry = true
        time = {
            connect = 10L
            write = 10L
            read = 10L
        }
        cache = {
            type = CacheType.NONE
            path = ""
            size = 10
            noNetworkTimeOut = 10
            networkTimeOut = 10
        }
        head = {
            put("hello", "world")
        }
        log = {
            level = LoggerLevel.BASIC
            interceptors = setOf(object : OnLogInterceptor {
                override fun onLogInterceptorInfo(message: String) {

                }
            })
        }

        adapter = {}
        converter = {}
        cookie = {}
    }
  }
Copy the code

Then there is use. Simple GET requests.

viewModel.viewModelScope.launch { moya.create() .parameter("username", "moya") .parameter("password", "123456") .parameter("repassword", "123456") .doPost<RegisterData>("user/register") .doComplete { hideLoadDialog() } .doFailed { showRequestDialog(it.message ? : " is empty ") } .doSuccess { showRequestDialog(it.toString()) } }Copy the code

Design ideas

In fact, I still want to share my experience with you. Let me show you the architecture of the project

  • Plug-ins are used for dependency management

This is mostly for convenience. That’s the way I forgot where I saw it. But I think it’s actually okay. A little more convenient than BuildSrc.

  • The project is divided into basic module and coroutine module

This is for extension. I thought I’d add the RxJava thing later. So a lot of the core functionality is in Moya.

  • All the extension functions of coroutines are performed by Kotlin’s extension functions

Mostly one word. Sweet!

About the configuration

This is easy. The constructor pattern is primarily used to create an object. The hole I ran into was in the DSL section. If I could implement it the way I did above. Take network timeout as an example.

Var moya.builder. time: NetWorkTimeOut.() -> Unit by LambdaDelegate<NetWorkTimeOut, Moya.Builder>( NetWorkTimeOut() ) { netWorkTime, builder -> builder.connectTimeout(time = netWorkTime.connect) builder.readTimeout(time = netWorkTime.read) builder.writeTimeout(time = netWorkTime.write) }Copy the code

The core code is just a few lines. It’s kind of interesting, of course, to extend functions and delegates. The effect of time{} can be realized. In order to control scope, the author still uses DslMarker to control it.

Dynamically Changing a URL

This requirement is rare, but yes, I’ve seen people create multiple Retrofit objects to control, which is bad. It can actually be controlled by interceptors. The author also wrote directly here. Simply add the following code to the request to dynamically replace the URL

baseUrl("new host url")
Copy the code

Principle, is interceptor, put on the core code, detailed can go to see the source code.

override fun intercept(chain: Interceptor.Chain): Response { var request = chain.request() val headers = request.headers if (headers.size > 0) { val url = headers[DynamicHeard.DYNAMIC_URL] if (url ! = null) { val httpUrl = request.url val newBuilder = httpUrl.newBuilder() checkBaseUrl(url, newBuilder) setNewHost(url, newBuilder) request = request.newBuilder() .removeHeader(DynamicHeard.DYNAMIC_URL) .url(newBuilder.build()) .build() return chain.proceed(request) } } return chain.proceed(request) }Copy the code

Dynamic request modification timed out

In fact, it is a relatively niche need. It can still be triggered by interceptors. Add the following code to the request to set the timeout time. Convenient,

.connectTimeOut(1)
Copy the code

The last

Writing this small framework, THE author also learned a lot, the understanding of Kotiln is better, the project is placed in moya interested readers can learn by themselves.

The last of the last. The new job is a little tired, but also found a lot of shortcomings. Look forward to the next level.