Flutter开发进阶之Package
通常我们在Flutter开发中需要将部分功能与整体项目隔离,一般有两种方案Plugin和Package,Application是作为主体项目,Module是作为原生项目接入Flutter模块。
当独立模块不需要与原生项目通讯只需要Plugin就可以,但是当需要与原生通讯就需要Package。
一、创建Package
cd /Users/kevin/Desktop/My
flutter create --org com.kevin --template=plugin --platforms=android,ios -a kotlin -i swift package_demo
创建Package必须指定平台:
android、ios、web、linux、macos 和 windows。
命令中-a后是指定Android的开发语言,-i是指定iOS的开发语言。
二、通讯
Package会自动创建MethodChannel,还可以根据需要创建BasicMessageChannel和EventChannel。
Flutter
class MethodChannelPackageDemo extends PackageDemoPlatform {
/// The method channel used to interact with the native platform.
final methodChannel = const MethodChannel('package_demo_method');
final messageChannel = const BasicMessageChannel('package_demo_message',
StandardMessageCodec());
final eventChannel = const EventChannel('package_demo_event');
MethodChannelPackageDemo() {
methodChannel.setMethodCallHandler((call) async {
/// 方法
return call.method;
});
messageChannel.setMessageHandler((message) async {
/// 字符串和半结构化
return message;
});
eventChannel.receiveBroadcastStream().listen((event) {
/// 事件流
}, onError: (error) {
///
}, cancelOnError: true,);
}
Future<String?> getPlatformVersion() async {
final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
return version;
}
}
iOS
public class PackageDemoPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let methodChannel = FlutterMethodChannel(name: "package_demo_method", binaryMessenger: registrar
.messenger())
let instance = PackageDemoPlugin()
registrar.addMethodCallDelegate(instance, channel: methodChannel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("iOS " + UIDevice.current.systemVersion)
default:
result(FlutterMethodNotImplemented)
}
}
}
Android
class PackageDemoPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var methodChannel : MethodChannel
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
methodChannel = MethodChannel(flutterPluginBinding.binaryMessenger, "package_demo_method")
methodChannel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}
三、调用原生控件
Flutter
class PackageView extends StatelessWidget {
const PackageView({super.key});
Widget build(BuildContext context) {
// TODO: implement build
if (Platform.isAndroid) {
return AndroidView(
viewType: 'package_demo/android',
onPlatformViewCreated: (id) {},
creationParams: const {'type': 'android'},
creationParamsCodec: const StandardMessageCodec(),
);
} else if (Platform.isIOS) {
return UiKitView(
viewType: 'package_demo/ios',
onPlatformViewCreated: (id) {},
creationParams: const {'type': 'ios'},
creationParamsCodec: const StandardMessageCodec(),
);
}
return const SizedBox();
}
}
iOS
public class PackageDemoPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let methodChannel = FlutterMethodChannel(name: "package_demo_method", binaryMessenger: registrar
.messenger())
let instance = PackageDemoPlugin()
registrar.addMethodCallDelegate(instance, channel: methodChannel)
registrar.register(PackageViewFactory(), withId: "package_demo/ios")
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("iOS " + UIDevice.current.systemVersion)
default:
result(FlutterMethodNotImplemented)
}
}
}
class PackageViewFactory: NSObject, FlutterPlatformViewFactory {
func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
return PackageView()
}
func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec.sharedInstance()
}
}
class PackageView: NSObject, FlutterPlatformView {
func view() -> UIView {
return UIView()
}
}
Android
class PackageDemoPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var methodChannel : MethodChannel
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
methodChannel = MethodChannel(flutterPluginBinding.binaryMessenger, "package_demo_method")
methodChannel.setMethodCallHandler(this)
flutterPluginBinding.platformViewRegistry.registerViewFactory("package_demo/android", PackageViewFactory());
}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
methodChannel.setMethodCallHandler(null)
}
}
class PackageViewFactory: PlatformViewFactory(StandardMessageCodec.INSTANCE){
override fun create(context: Context?, viewId: Int, args: Any?): PlatformView {
return PackageView(context)
}
}
class PackageView internal constructor(context: Context?): PlatformView{
override fun getView(): View? {
TODO("Not yet implemented")
}
override fun dispose() {
TODO("Not yet implemented")
}
}
四、添加进项目
Package创建成功后可以放置在本地或者上传到github,通过path:或者git: \n url: \n ref: 去添加进项目,通过指定版本去建立依赖。