Flutter Learning Guide 6. file storage and networking 5. interaction, gestures and animation 4.UI layout and controls 3. Familiar with Dart language 2. Write the first application 1. Build development environment
This is the seventh article in a series of study guides.
In this article, we will learn how to use the Flutter plugin together, then learn how to develop the Flutter plugin by developing a Toast plugin, and finally publish it to Pub.
Use of plug-ins
The library of Flutter is managed as a package. Package is divided into two types, Dart Package (also called Library Package) and Plugin Package. When we say Fluter package, we also mean Dart package, which can only use Dart and Flutter apis. When we say the Flutter plugin, we mean the plugin package. The Flutter plugin usually contains platform-specific code. To the user of the package, there is no difference.
Add the dependent
To use a library, we first declare a dependency in pubspec.yaml:
dependencies:
Shared_preferences: ^ 0.4.2
Copy the code
^0.4.2 indicates a version compatible with 0.4.2. We can also specify a specific version of the dependent library:
- Any: Any version
- 1.2.3: Specific version
- <1.2.3: version less than 1.2.3, in addition to <=, >, >=
- ‘>=1.2.3 <2.0.0’ : specifies a range
Next, perform the flutter Packages GET in the root directory of the project. If you are developing using Android Studio, you can also click the Packages Get button directly on the pubspec.yaml edit page.
The above example is the library published on pub.dartlang.org. In addition, we can also use other sources:
dependencies:
transmogrify:
hosted:
name: transmogrify
url: http://your-package-server.com
Version: ^ 1.4.0
kittens:
git:
url: git://github.com/munificent/cats.git
Ref: some-branch # Optional
kittens:
git:
url: git://github.com/munificent/cats.git
Path: path/to/kittens # Specifies a path
You can even specify a local path
transmogrify:
path: /Users/me/transmogrify
Copy the code
If you have read the PubSpec of Flutter, you will have noticed that Flutter declares:
dependencies:
flutter:
sdk: flutter
Copy the code
The SDK is used to import packages shipped with Flutter, currently only Flutter.
use
After importing the relevant package, we can use its API:
import 'package:shared_preferences/shared_preferences.dart';
void foo() async {
var prefs = await SharedPreferences.getInstance();
var used = prefs.getBool('used');
if(! used) {
prefs.setBool('used'.true);
}
}
Copy the code
The problem with this type of import is that it imports all the symbols in the library into the global namespace (for example, in the example above, we can use SharedPreferences directly). Sometimes to prevent namespace contamination, we can use AS to give the imported library a name (of course, it is not necessary to use the qualified name for SharedPreferences) :
void foo() async {
var prefs = await sp.SharedPreferences.getInstance();
var used = prefs.getBool('used');
if(! used) {
prefs.setBool('used'.true);
}
}
Copy the code
Now that we know how to use the Flutter package, let’s develop our own Flutter plugin.
Developing a plug-in
While learning about Flutter, I wonder if you have noticed that Flutter does not provide a Toast API. To remedy this, in this section we will develop a plug-in that supports Toast.
Before we start development, let’s take a look at how Flutter communicates with platform-specific code.
MethodChannel
Flutter can communicate with platform-specific code via the MethodChannel. The client uses MethodChannel to send method calls and parameters to the server, which also receives the relevant data through MethodChannel.
Note that the arrows in the figure above are two-way. That is, we can not only call Android/iOS code from Flutter, but also from Android/iOS. The related parameters are as follows:
Dart | Android | iOS |
---|---|---|
null | null | nil (NSNull when nested) |
bool | java.lang.Boolean | NSNumber numberWithBool: |
int | java.lang.Integer | NSNumber numberWithInt: |
int, if 32 bits not enough | java.lang.Long | NSNumber numberWithLong: |
double | java.lang.Double | NSNumber numberWithDouble: |
String | java.lang.String | NSString |
Uint8List | byte[] | FlutterStandardTypedData typedDataWithBytes: |
Int32List | int[] | FlutterStandardTypedData typedDataWithInt32: |
Int64List | long[] | FlutterStandardTypedData typedDataWithInt64: |
Float64List | double[] | FlutterStandardTypedData typedDataWithFloat64: |
List | java.util.ArrayList | NSArray |
Map | java.util.HashMap | NSDictionary |
Create a project
This assumes that the reader is developing using Android Studio.
- On the menu, choose File -> New -> New Flutter Project
- Select the Flutter Plugin from the panel that pops up and click Next
- For Project name, we fill in Flutter_toast2018, and for other information, readers fill in according to their own needs
It is called flutter_toast2018 because there is already a Flutter_toast on the Pub, so 2018 is added to prevent name conflicts.
The generated project has four main directories:
- Android: Android implementation of plug-in native code
- Ios: implementation of ios
- Lib: Dart code. The plug-in’s customers will use the interface implemented here
- Example: An example of a plug-in
Plug-in development
Android end code implementation
In fact, when we generated the project in the last step, there was already a demo of Flutter that implemented platformVersion. Readers who are interested in Flutter can take a look. Next, let’s develop our own Toast plug-in (note that our implementation only supports Android).
First let’s look at the interface MethodCallHandler:
public interface MethodCallHandler {
void onMethodCall(MethodCall call, Result result);
}
Copy the code
This interface is used to process local method calls to Flutter. That is, we need to implement the interface that pops up a toast when a Flutter calls us.
This interface is implemented by the FlutterToast2018Plugin (located in the Android directory) :
public class FlutterToast2018Plugin implements MethodCallHandler {
public static void registerWith(Registrar registrar) {
// "example.com/flutter_toast2018" is the name of our method channel, which is also needed in the Dart code.
// To prevent naming conflicts, you can prefix it with the domain name
final channel = new MethodChannel(registrar.messenger(), "example.com/flutter_toast2018");
channel.setMethodCallHandler(new FlutterToast2018Plugin());
}
@Override
public void onMethodCall(MethodCall call, Result result) {
// TODO
}
}
Copy the code
To pop Toast, we add a Context parameter to the constructor of the FlutterToast2018Plugin:
public class FlutterToast2018Plugin implements MethodCallHandler {
private final Context mContext;
public FlutterToast2018Plugin(Context context) {
mContext = context;
}
/ / register MethodCallHandler
public static void registerWith(Registrar registrar) {
final channel = new MethodChannel(registrar.messenger(), "example.com/flutter_toast2018");
// The context is via Registrar
channel.setMethodCallHandler(new FlutterToast2018Plugin(registrar.context());
}
// ...
}
Copy the code
Now, implement the onMethodCall method:
public class FlutterToast2018Plugin implements MethodCallHandler {
// ...
@Override
public void onMethodCall(MethodCall call, Result result) {
// Call. Method is the name of the method
if (call.method.equals("toast")) {
// Only one argument can be passed when calling native code. To pass multiple parameters, you can put them in a map.
The call.arguemnt() method supports Map and JSONObject
String content = call.argument("content");
String duration = call.argument("duration");
Toast.makeText(mContext, content,
"short".equals(duration) ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG)
.show();
// The command is successfully executed
result.success(true);
} else {
result.notImplemented();
}
}
}
Copy the code
The Flutter end
All the Flutter side needs to do is generate a MethodChannel and call the toast method with this MethodChannel:
import 'dart:async';
import 'package:flutter/services.dart';
enum ToastDuration {
short, long
}
class FlutterToast {
// The name must correspond to the Java side
static const MethodChannel _channel =
const MethodChannel('example.com/flutter_toast2018');
static Future<bool> toast(String msg, ToastDuration duration) async {
var argument = {
'content': msg,
'duration': duration.toString()
};
// The local method is an asynchronous call. 'toast' corresponds to the onMethodCall in our previous Java code
// The name of the method handled inside the method
var success = await _channel.invokeMethod('toast', argument);
return success;
}
}
Copy the code
The use of plug-in
In this section we modify the example in the example directory of the project to demonstrate the use of the plug-in:
import 'package:flutter/material.dart';
// Import our package first
import 'package:flutter_toast2018/flutter_toast2018.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Plugin example app'),
),
body: new Center(
child: RaisedButton(
child: Text('toast'),
// Plugins are used in the same way as other libraries
onPressed: () => FlutterToast2018.toast(
'Toast from Flutter', ToastDuration.short
),
),
),
),
);
}
}
Copy the code
Release the plugin
As mentioned earlier, PubSpec supports importing dependencies through local paths and Git, but for better management of version dependencies, it is recommended to publish plug-ins to pub.dartlang.org/. In this section, we publish the Toast plug-in we developed earlier to the Pub.
It should be noted that for some well-known reason, Pub.dartlang.org requires a ladder to get up. Although we can also publish flutter- IO. Cn, uploading requires a Google account and a ladder.
Check the configuration
The first is pubspec.yaml. For the Flutter plugin, PubSpec also contains some meta information that readers can fill in as needed, in addition to the plugin dependencies:
name: flutter_toast2018
description: A new Flutter plugin for Android Toast.
Version: 0.0.1
author: Jekton <[email protected]>
homepage: https://jekton.github.io/
Copy the code
In addition, packages published to Pub need to include a LICENSE file, and the easiest way to do this is to select one when creating a repository on GitHub.
Check the plugin
Now, let’s check for any problems with the plug-in by executing the following command at the root of the project:
flutter packages pub publish --dry-run
Copy the code
If all is well, it will print:
.
Package has 0 warnings.
Copy the code
Release the plugin
Publishing the plug-in is the same as the previous step, but without the dry-run argument:
flutter packages pub publish
Copy the code
If this is your first Posting, you will be prompted to verify your Google account. Successful matches package is displayed after the file is uploaded.
Looks great! Are you ready to upload your package (y/n)? y
Pub needs your authorization to upload packages on your behalf.
In a web browser, go to https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&response_type=code&client_id=xxxxxxxxxxxxxx-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A52589&scope=https%3A%2F %2Fwww.googleapis.com%2Fauth%2Fuserinfo.email
Then click "Allow access".
Waiting for your authorization...
Successfully authorized.
Uploading...
Successful uploaded package.
Copy the code
We published in front of the package can be pub.dartlang.org/packages/fl… Or pub. Flutter – IO. Cn/packages/fl… To find it.
The relevant code is posted on GitHub:
git clone https://github.com/Jekton/flutter_toast2018.git
Copy the code
Finally, the Flutter package that we didn’t talk about. To develop a Flutter package, we can select the Flutter Package when creating a project. The only difference between this and the Flutter plugin is that the Flutter package cannot contain platform-specific code (only Dart and the Flutter API can be used). Otherwise, development, distribution, and use of Flutter are no different from the Flutter plugin.
Welcome to scan code attention