Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities.

This paper also participates inProject DigginTo win the creative gift package and challenge the creative incentive money.

preface

These days, I will check whether the Moya plug-in can be optimized in my own project.

Sometimes when you look at Moya, you wonder what kind of brainwave came into being to write a web request library like this.

We talk about Alamofire all the time, and of course going from 0 to 1 is an incredibly difficult and great feat.

But I think Moya is a 1 to 100 process that makes Swift’s network requests unprecedented and unprecedented.

PluginType agreement

Let’s look at the PluginType protocol in Moya.

/// A Moya Plugin receives callbacks to perform side effects wherever a request is sent or received. /// /// for example, a plugin may be used to /// - log network requests /// - hide and show a network activity indicator /// - inject additional information into a request public protocol PluginType { /// Called to modify a request before sending. func prepare(_ request: URLRequest, target: TargetType) -> URLRequest /// Called immediately before a request is sent over the network (or stubbed). func willSend(_  request: RequestType, target: TargetType) /// Called after a response has been received, but before the MoyaProvider has invoked its completion handler. func didReceive(_ result: Result<Moya.Response, MoyaError>, target: TargetType) /// Called to modify a result before completion. func process(_ result: Result<Moya.Response, MoyaError>, target: TargetType) -> Result<Moya.Response, MoyaError> }Copy the code

If you want to write a Moya plugin, you can just follow the protocol and implement it. The default implementation of the Moya plugin is also done.

class LoadingPlugin: PluginType {

}
Copy the code

Moya’s built-in plugins — NetworkActivityPlugin and NetworkLoggerPlugin

Moya has already provided us with two very useful plugins, NetworkActivityPlugin and NetworkLoggerPlugin. From the name we can see its purpose.

NetworkActivityPlugin

This plugin is used to add loading pages before and after network requests.

/// Called by the provider as soon as the request is about to start
public func willSend(_ request: RequestType, target: TargetType) {
    networkActivityClosure(.began, target)
}

/// Called by the provider as soon as a response arrives, even if the request is canceled.
public func didReceive(_ result: Result<Moya.Response, MoyaError>, target: TargetType) {
    networkActivityClosure(.ended, target)
}
Copy the code

When the plug-in is initialized, loading can be added or removed by judging the began and ended states.

It can be said that through the way of plug-in, so that the network request data level and UI page changes are isolated, non-interference, and easy to maintain.

NetworkLoggerPlugin

When it comes to web requests, printing JSON is unavoidable in App development.

In Alamofire, there is a printed solution internally, implemented through Notification, while in Moya it is implemented through Plugin.

There’s nothing special about this feature, just integrate it.

The plug-in USES

ActivityPlugin:

let activityPlugin = NetworkActivityPlugin { (state, targetType) in switch state { case .began: Case. Ended: // Close loading to complete logic}}Copy the code

LoggerPlugin:

let loggerPlugin = NetworkLoggerPlugin()
Copy the code

Integrating with providers:

let myProvider = MoyaProvider<MyService>(plugins: [loggerPlugin, activityPlugin])
Copy the code

One Plugin for one feature

In fact, in essence, loading business and logger printing can be completed in one Plugin, so why is Moya split into two?

In my opinion, Moya tends to break down functions into small ones and decouple each small function, so that it is more flexible in the use of trade-offs.

For example, IF I only want to print JSON in Debug mode but not in Release mode, then I don’t need to use loggerPlugin in Release mode.

Remember a Plugin, a feature.

PluginType protocol and interceptors

Look at the PluginType protocol function names and comments:

  • Prepare: Called modify a request before sending

  • WillSend: Called immediately before a request is sent over the network (or stubbed)

  • DidReceive: Called after a response has been received, but before the MoyaProvider has invoked its completion handler

  • Process: Called to modify a result before completion.

The declaration cycle of a web request can be used to block web requests in Android and Flutter development.

The following code is from Dio in Dart:

extension AddPrettyPrint on Dio {
  Dio get addPrettyPrint {
    this.interceptors.add(
          PrettyDioLogger(
            requestHeader: false,
            requestBody: true,
            responseBody: true,
            responseHeader: false,
            compact: false,
          ),
        );
    return this;
  }
}

static Dio _dio = Dio(
    BaseOptions(
      baseUrl: Api.baseUrl,
      connectTimeout: timeout,
      receiveTimeout: timeout,
      headers: {},
    ),
  ).addPrettyPrint;
Copy the code

This code adds a PrettyDioLogger interceptor to Dio, and then prints information about network requests in the request and response of network requests.

Protocol oriented programming

Moya is a great blueprint for protocol oriented programming, and I think the core of protocol oriented programming is:

  • I just care if the method is implemented or not, but how

    Implementation becomes Coder’s business, flexible.

  • Use strong constraints to let Coder do things according to the rules, do not follow the rules, sorry, error

    Constraints become iron laws, reducing coding errors.

  • Protocols can be thought of as multiple inheritance in disguise

    By flattening out the distinction between types and functions, generics and function types can be constrained by protocol types, making programming simpler and more flexible, as well as more difficult to understand.

Sometimes, writing protocol oriented programming for a long time, will miss object-oriented programming.

Why? Because protocol oriented programming doesn’t have inheritance.

Let’s say I have A business A and I have A business B, where business B is one more method than business A.

Object oriented speech class B: A, and Protocol oriented struct A: Protocol, struct B: Protocol.

Struct has no way to inherit, page B obviously just adds some functions on the basis of page A, and B can only add functions after copying A code of A.

I don’t want to preach protocol oriented programming or object oriented programming here, it’s about being there, it’s about being flexible.

And protocol-oriented programming isn’t unique to Swift either. Just look next door at Dart, which extends, implements, and with. We have one:.

class PAAppBar extends StatelessWidget implements PreferredSizeWidget {

}
Copy the code

Reference documentation

The use of moya

conclusion

This article discusses two plugins, NetworkActivityPlugin and NetworkLoggerPlugin, from Moya abstract PluginType protocol, and explains how to use them.

Some similarities and differences between PluginType protocol and Dio interceptor are compared.

Finally, we return to the protocol itself and illustrate the characteristics of protocol-oriented programming.

Hope to help you.