Plug-ins are essential to the flutter ecology. The plugin allows developers to interact with the platform on which the app is running.

As of October 2018, there are hundreds of plugins available on pub.dev. The quality of the plugin is especially important, whether it’s from Google or a third party. This article explores what makes a good plug-in and how to build one.

Functionality comes first, APIs second

Many times when you write a plug-in, you bridge over a library that already exists locally. The most straightforward way to do this is to write the corresponding DART API based on the native library API. But when APIs don’t match up well due to platform differences, you have to expose more of the native API details, leading to a lot of bad results.

When you write plug-ins, prioritize functionality, not APIs. For example, if you’re writing a local storage plug-in, the API you might need is

  • Can store various types of values
  • With that in mind, you can start thinking about how to design your Dart API:
class StoragePlugin {
  
  /// Reads a string
  Future<String> getString(String key) async {}
  
  /// Writes a string
  Future<void> setString(String key, String value) async {}
}

Copy the code

With that done, let’s focus on exposed apis and how to adapt to the platform:

class StoragePlugin {
  
  Future<String> getString(String key) async {
    if (Platform.isIos) {
      return await callMethodChannel('fetchValue', {'id': base64encode(key)});
    } else if (Platform.isAndroid) {
      return await callMethodChannel('fetchValue', {'id': key});
    }
  }
  
  Future<void> setString(String key, String value) async {
    if (Platform.isIos) {
      await callMethodChannel('setValue', {'id': base64encode(key), 'value': value});
    } else if (Platform.isAndroid) {
      await callMethodChannel('setValue', {'id': key, 'value': value}); }}}Copy the code

If you provide a feature that is not supported by a platform, the API needs to provide a reasonable error message. Do not break the app, and the unsupported operation should be commented out. You should continue to request platform to complete this unsupported operation to go through the plug-in call flow.

Avoid platform-specific approaches

Flutter itself is cross-platform. It is not appropriate to write platform-specific code. If the plug-in user wants to do the following:

if (Platform.isIos) {
  myPlugin.doIOSThing();
} else if (Platform.isAndroid) {
  myPlugin.doAndroidThing();
}
Copy the code

Consider handing platform-specific logic over to the plugin itself, which could look like this:

myPlugin.doThing();
Copy the code

Avoid supporting only one platform

You may want to start by writing a “small but beautiful” plugin that only supports Android. Unfortunately, when plugins are released, they can cause problems for users of unsupported platforms, namely developers.

For example, the Android platform plugin, Android Intent, if not displayed, you can directly visit github.com/flutter/plu…

Make your plugin easier to understand and test

As a rule of thumb, your plug-in should contain a lot of Dart code.

  • The native layer is important because it performs functions that libraries do not work with emulators.
  • Flutter is mostly written by Dart. The Flutter app does the same, so that when you track code, you can freely follow up within Dart.

The only reason to use the Native layer should be if the platform-specific implementation needs to save state or do some other processing. A good example is that biometrics on Android has its own complex life cycle, which requires Native code to manage. If you need to write a lot of native code, consider the single authority rule and divide it into different classes for unit testing.

Ideally, your plug-in simply listens for method calls and sends the results back to the Dart side. If you’re doing more than that, see if you can move more to the Dart side, and eventually your code logic will be reused across multiple platforms, such as Web, Android, and ios.

Avoid writing static (or global) functions

Such as:

Future<User> authenticate() async {
  // Some code
}
Copy the code

But the following is even better:

class AuthenticatePlugin {
  Future<User> authenticate() async {
    // Some code
  }
}
Copy the code

This makes plug-ins easier to mock. The user can easily replace the real implementation and then the app can run on an emulator or test tool.

Conclusion: Plugins made the Flutter bald and stronger. Write your own plugin!! Come on SAO years


Just give it a thumbs up.