Flutter has a better way in plugin development. They called it Federated Plugin. It is like in politic’s federated states where the state is the plugin for the specific platform. With this new way, any third-party can contribute to implement the plugin for a specific platform.
Let say you want to create a simple plugin to display a message box. You call it message_box plugin. The message box can be customized for error message or info message. First, you have to define the interface of the plugin:
abstract class MessageBoxPlatform extends PlatformInterface {
Future<void> showInfoMessage(string description, string title = "Error");
Future<void> showErrorMessage(string description, string title = "Info");
}
The Packages Diagram
The standard naming convention for the interface definition is <plugin_name>Platform . You have to put the interface definition inside its own Flutter package and this is the packages map of the whole plugin and the client application that is using the plugin:
The client_application usually only depends to the main plugin package which is the message_box package. But if the plugin writer hasn’t implement the plugin for any specific platform needed by the client_application then any third party can implement the plugin platform interface and the client_application can use that implementation. In our case the message_box_web is written by third-party so that is why the main plugin package doesn’t have dependency to the web implementation. The message_box_platform_interface depends on the plugin_platform_interface defined by Flutter. The plugin_platform_interface provide the necessary infrastructure for mocking the plugin and making sure the plugin is implementing Singleton pattern properly.
Each platform implementation package will contains the Dart and native codes to implement the plugin platform interface. The main plugin package will only contains the Façade or wrapper that simplify the usage of the plugin.
Below is the more complete map of the packages diagram:
Registration Phase
When you install a package containing plugin then Flutter will generate code to call the plugin registration function. As you can see from the complete diagram above, each platform implementation will have a static registerWith() method. This method will be called automatically by Flutter. Once the method called then the Singleton instance will be assigned with the specific platform implementation as shown by the note in the above diagram.
On iOS you can see above, there will be code added by Flutter that called the generated plugin registration on line 14 above. But for Android since the Android Plugin API 2.0, there should be no call to any generated plugin registration, you can read more here.
The Call Flow
Once the plugin successfully registered then you can start using the functionalities it has to offered. To better understand the flow when you call the one of the plugin method, you can study the sequence diagram below:
Pigeon vs Method Channel
To call the native code we have two options. The conventional way is to use method channel directly. The newest way is to use Pigeon package and it will generate the method channel’s code based on the interface that we specified. Myself prefer to use Pigeon because it abstracted away the plumbing code and we can just focus on writing the specific platform implementation.