The background,

In the daily development process, the network request function is essential, so a series of network loading libraries have been derived from it, such as URLConnection, Volley, OkHttp, Retrofit, etc. As the requirements change over the course of the project, the network loading libraries we use may also change (replace the network loading libraries). Therefore, this chapter describes how to design a network library isolation framework, when there is a network loaded library replacement, the source code changes as little as possible (in accordance with the open closed principle, extension is open, modification is closed).

Second, design ideas

The first thing to understand is that there are many interfaces to use the web request functionality (such as login, various data fetching, file uploading, etc.), so the first problem to deal with is how to avoid the web loading library interacting directly with the page request. When there is a network library replacement, a large number of direct interactions must result in a large number of source code modifications, which are shown to violate our open and closed principles.

Then there is how to introduce a new and replaced network loading library, which is equivalent to adding the various request functions of another network library. The end result is that we use different network libraries to perform the same function, and since the function is consistent, we need to consider how to standardize their function (function) definition.

Based on the above two considerations, we adopt proxy mode to implement our network library isolation framework.

Third, design mode

1. The architecture diagram

2. Show

(1) Proxy mode: provides a Proxy for other objects to control access to that object. (2) Proxy Proxy class: replaces the actual network loading library and avoids direct interaction between interface code and the actual network loading library. (3) RealSubject: Real request class, in our case, a network loading library. (4) Subject: It is used to regulate the function use of newly added various network loading libraries and proxy classes. Why regulate the function of proxies? Because proxy classes are proxies for the functional behavior of real classes, proxy classes need to be consistent with the functionality of real classes.

Four, Kotlin implementation

1.Subject

ICallBack is a custom request callback class. ICallBack is a custom request callback class. ICallBack is a custom request callback class. String, callback: ICallBack) fun postHttp(url: String, params: Map<String, Any>, callback: ICallBack) }Copy the code

2.Proxy

Private var httpProxyImpl :IHttpProxy? Private var httpProxyImpl :IHttpProxy Override fun getHttp(url: int int){httpProxyImpl = httpImpl} String, callback: ICallBack) {// Call the real object method httpProxyImpl!! .getHttp(url,callback) } override fun postHttp(url: String, params: Map<String, Any>, callback: ICallBack) {// At runtime, call the real object method httpProxyImpl!! .postHttp(url,params,callback) } }Copy the code

(1) the Kotlin grammar do not understand, please see the following articles 【 】 Kotlin_ the first line of code www.jianshu.com/nb/35111692 (2) the proxy class, implements the interfaces defined above, and implements the corresponding function, and you can see, (3) The proxy class must hold a reference to the real class, otherwise it cannot implement the proxy function on the real class. (4) The init method means passing in the real class object that needs to be proided

3.RealSubject

// Implement proxy mode interface class OkHttpProxyImpl: Var handler = handler (looper.getLooper ()) override fun getHttp(url: String, callback: Val mOkHttpClient = okHttpClient () val Request = request.Builder () .url(url).build() //new Call Val Call = mokHttpClient. newCall(request) // Request to join call.enqueue(object: Callback { override fun onFailure(call: Call, e: IOException) { handler.post { callback.onFailure(e.toString()) } } override fun onResponse(call: Call, response: Response) {if (response.isSuccessful) {
                    val string = response.body()?.string()
                    handler.post {
                        callback.onSuccess(string!!)
                    }
                } else {
                    handler.post {
                        callback.onFailure(response.message())
                    }
                }
            }
        })
    }

    override fun postHttp(url: String, params: Map<String, Any>, callback: ICallBack) {
    }
}

Copy the code

This class is a real class that we implemented using the OkHttp network loading library. To achieve the corresponding interface, and in the corresponding function, to achieve the real network request function, and the use of custom callback function, the result callback to the use of the place (3) currently only achieve get function logic function, post function the same.

4. Custom callback functions (ICallBack, IHttpCallBack)

// The lowest callback class, String, represents the returned JSON, XML format file, i.e. the primary data returned by the network request, no operation on the data interface ICallBack {fun onSuccess(result: String) fun onFailure(result: String) }Copy the code
// Abstract class IHttpCallBack<T> : Override fun onSuccess(result: override fun onSuccess(result: String) { val obj = (Gson().fromJson(result, getRealType(this))) val realObj: T? = try { obj as T } catch (e: Exception) { null } onSuccess(realObj!!) } abstract fun onSuccess(result: T)/private fun getRealType(any: any) Any): Class<*> { val genType = any.javaClass.genericSuperclass val params = (genType as ParameterizedType).actualTypeArgumentsreturn params[0] as Class<*>
    }

}
Copy the code

5. Interface request

// A simple layout of a TextView + a ButtonAppCompatActivity() {// wanAndroid open API, thank you very much, get public number list val URL ="https://wanandroid.com/wxarticle/chapters/json"override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState) // Button click event json_get_btn.setonClickListener {// Proxy object is used here. It is the proxy object that interacts directly with the interface, not the concrete network-loading class object. Httphelper. getHttp(URL, object: httphelper. getHttp) IHttpCallBack<Author>() {ICallBack override fun onSuccess(result: ICallBack Override fun onSuccess(result: Author) {// json_result_tv is the TextView in the layout, Json_result_tv.text = result.getInfo() toast.maketext (this@MainActivity,"Request successful", toast.length_short).show()} // Override fun onFailure(result: String) { json_result_tv.text = result Toast.makeText( this@MainActivity,"Request failed", Toast.LENGTH_SHORT
                    ).show()
                }
            })
        }
    }
}
Copy the code

(1) It should be noted that before using the proxy class, the object of the proxy class needs to be passed in first. This case is set during Application initialization

class MyApp :Application() {
    override fun onCreate() {super.oncreate () httphelper.init (OkHttpProxyImpl()) // Set the real proxy object}}Copy the code

6. Replace the network loading library step

(1) Implement a real class corresponding to the network loading library, such as VolltyProxyImpl, modeled after OkHttpProxyImpl.

// Volley VolleyProxyImpl :IHttpProxy {override Fun postHttp(url: String, params: override Fun postHttp) Map<String, Any>, callback: ICallBack) {override fun getHttp(url: String, callback: ICallBack) ICallBack) {// Specific volley get request}}Copy the code

(2) Replace the proxied object in the proxy class, that is, modify the code in MyApp

class MyApp :Application() {
    override fun onCreate() {super.oncreate () httphelper.init (VolltyProxyImpl()) // Set as a new netload class object}Copy the code

}

7. The last

At this point, our network isolation library framework prototype has been built, more functions please customize expansion. If there is any incorrect place, welcome to criticize and correct. Thank you very much [Tencent Classroom -Android Advanced Development seminar]

[Project Address] : github.com/y0000c/Http…