Flutter开发进阶之Package

Flutter开发进阶之Package

通常我们在Flutter开发中需要将部分功能与整体项目隔离,一般有两种方案Plugin和Package,Application是作为主体项目,Module是作为原生项目接入Flutter模块。

当独立模块不需要与原生项目通讯只需要Plugin就可以,但是当需要与原生通讯就需要Package。

一、创建Package

python 复制代码
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
dart 复制代码
class MethodChannelPackageDemo extends PackageDemoPlatform {
  /// The method channel used to interact with the native platform.
  @visibleForTesting
  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,);

  }
  
  @override
  Future<String?> getPlatformVersion() async {
    final version = await methodChannel.invokeMethod<String>('getPlatformVersion');
    return version;
  }
}
iOS
swift 复制代码
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
kotlin 复制代码
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
dart 复制代码
class PackageView extends StatelessWidget {
  const PackageView({super.key});

  @override
  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
swift 复制代码
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
kotlin 复制代码
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: 去添加进项目,通过指定版本去建立依赖。

相关推荐
_祝你今天愉快7 小时前
从驱动来分析服务的添加过程
android
Dovis(誓平步青云)10 小时前
折叠屏悬停看视频,上半屏和下半屏应该各做什么
android·java·服务器·开发语言·安全·音视频
思盛iOS签名上架11 小时前
App苹果签名有什么作用?
macos·ios·cocoa
alexhilton11 小时前
让架构边界变成可执行的测试
android·kotlin·android jetpack
hai_android12 小时前
SendChannel 与 ReceiveChannel 通信机制
android
CocoaKier13 小时前
Facebook广告后台收不到Adjust回传数据,我们排查了一个月终于找到了根因
ios·facebook
数据治理自习室14 小时前
AI 应用评测体系(GraphRAG)
android·大数据·人工智能·kotlin
爱笑鱼15 小时前
Android 系统启动机制(五):system_server 是 init 启动的,还是 Zygote fork 出来的?
android
智购科技无人售货机工厂16 小时前
2026自动售货机防拆机物理安全设计:从安全螺丝到结构互锁的工程实践~YH
android·网络·驱动开发·python·单片机·安全·云原生
开开心心就好16 小时前
电子教鞭工具支持画框写字插图片功能齐全
android·开发语言·前端·javascript·人工智能·pdf·html