Flutter平台接口抽象插件plugin_platform_interface的使用
Flutter平台接口抽象插件plugin_platform_interface
的使用
插件概述
plugin_platform_interface
包为联合Flutter插件提供了一个基础类。该包确保了平台接口被继承而不是实现,以保证新增的方法不会被视为破坏性变更。通过扩展平台接口,子类可以从基类中获取默认实现;而如果使用实现(implements),则在接口新增方法时会导致现有实现失效。
此包提供的功能强制平台接口必须被继承而不是实现,以此来提供公共的功能和约束。
示例用法
以下代码展示了如何定义一个平台接口,并为其提供默认实现:
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
abstract class SamplePluginPlatform extends PlatformInterface {
/// 构造函数,需要传入token用于验证
SamplePluginPlatform() : super(token: _token);
static final Object _token = Object();
// 定义静态成员变量_instance,持有当前的实例,默认是SamplePluginDefault。
static SamplePluginPlatform _instance = SamplePluginDefault();
// 提供getter和setter访问_instance
static SamplePluginPlatform get instance => _instance;
/// 平台特定的实现应该将此属性设置为它们自己的平台特定类,
/// 该类应扩展 [SamplePluginPlatform] 并在注册自己时调用。
static set instance(SamplePluginPlatform instance) {
// 验证新的实例是否正确地扩展了平台接口
PlatformInterface.verify(instance, _token);
_instance = instance;
}
// 插件平台接口的方法会在此处定义,通常这些方法会抛出 UnimplementedError 异常
}
// 默认的具体实现
class SamplePluginDefault extends SamplePluginPlatform {
// 实现平台接口中的方法
}
上述代码保证了 SamplePluginPlatform.instance
不能被设置为实现了 SamplePluginPlatform
的对象(只能设置为扩展了它的对象)。
模拟或伪造平台接口
测试平台接口的实现(如使用 mockito
的 Mock
或 test
的 Fake
)会在 verify
验证时失败。本包提供了 MockPlatformInterfaceMixin
,它可以在测试代码中使用,以禁用 extends
约束。
例如,可以创建一个模拟的平台接口如下:
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:mockito/mockito.dart';
class SamplePluginPlatformMock extends Mock with MockPlatformInterfaceMixin implements SamplePluginPlatform {}
关于base
关键字的一点说明
在Dart 3中引入了base
关键字,它在编译时强制要求子类使用extends
而非implements
。Flutter团队正在考虑弃用这个包转而使用base
关键字来定义平台接口,但目前还没有做出决定,因为这将移除上文提到的模拟/伪造的能力。
插件作者在创建新插件时可能希望考虑使用base
关键字代替这个包。
参考链接:GitHub Issue #127396
完整示例Demo
下面是一个完整的示例,演示了如何创建一个简单的插件,并使用plugin_platform_interface
定义其平台接口:
main.dart
import 'package:flutter/material.dart';
import 'package:sample_plugin/sample_plugin.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Plugin Example')),
body: Center(
child: ElevatedButton(
onPressed: () async {
String result = await SamplePlugin().doSomething();
print(result); // 输出结果
},
child: Text('Do Something'),
),
),
),
);
}
}
sample_plugin.dart
import 'package:flutter/services.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
abstract class SamplePluginPlatform extends PlatformInterface {
SamplePluginPlatform() : super(token: _token);
static final Object _token = Object();
static SamplePluginPlatform _instance = SamplePluginDefault();
static SamplePluginPlatform get instance => _instance;
static set instance(SamplePluginPlatform instance) {
PlatformInterface.verify(instance, _token);
_instance = instance;
}
Future<String> doSomething();
}
class SamplePluginDefault extends SamplePluginPlatform {
@override
Future<String> doSomething() async {
return "Default Implementation";
}
}
class SamplePlugin {
Future<String> doSomething() async {
return await SamplePluginPlatform.instance.doSomething();
}
}
以上就是关于plugin_platform_interface
的基本介绍和使用方法,希望对您有所帮助!
更多关于Flutter平台接口抽象插件plugin_platform_interface的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter平台接口抽象插件plugin_platform_interface的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter开发中,plugin_platform_interface
包是一个关键组件,它提供了一套通用的接口和抽象类,用于在跨平台插件中实现平台特定的逻辑。通过使用这些接口和抽象类,插件开发者可以确保他们的插件在不同平台上具有一致的API,同时允许平台特定的实现。
下面是一个简单的示例,展示了如何在Flutter插件中使用 plugin_platform_interface
来创建一个跨平台的接口,并在iOS和Android平台上实现它。
1. 创建插件接口
首先,在你的Flutter插件项目中,创建一个新的Dart文件来定义你的插件接口。例如,创建一个名为 my_plugin_interface.dart
的文件:
// my_plugin_interface.dart
import 'dart:async';
// 定义插件接口
abstract class MyPluginInterface {
// 一个示例方法,用于获取平台特定的信息
Future<String> getPlatformInfo();
}
2. 创建平台实现
接下来,你需要为不同的平台(如iOS和Android)创建实现该接口的具体类。
iOS 实现
在你的iOS平台实现中,创建一个Swift或Objective-C文件来实现这个接口。例如,创建一个名为 MyPlugin.swift
的文件:
// MyPlugin.swift
import Flutter
public class MyPlugin: NSObject, FlutterPlugin, MyPluginInterface {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "com.example.my_plugin", binaryMessenger: registrar.messenger())
let instance = MyPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
_ = channel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) in
switch call.method {
case "getPlatformInfo":
let platformInfo = instance.getPlatformInfo()
result(platformInfo)
default:
result(FlutterMethodNotImplemented)
}
})
}
public func getPlatformInfo() -> String {
return "iOS"
}
}
注意,这里我们使用了 FlutterMethodChannel
来处理来自Dart代码的方法调用,并返回平台特定的信息。
Android 实现
在你的Android平台实现中,创建一个Kotlin或Java文件来实现这个接口。例如,创建一个名为 MyPlugin.kt
的文件:
// MyPlugin.kt
package com.example.my_plugin
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import android.app.Activity
class MyPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
private lateinit var channel: MethodChannel
private var activity: Activity? = null
override fun onAttachedToEngine(binding: FlutterPluginBinding) {
channel = MethodChannel(binding.binaryMessenger, "com.example.my_plugin")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformInfo") {
result.success("Android")
} else {
result.notImplemented()
}
}
override fun onDetachedFromEngine(binding: FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activity = binding.activity
}
override fun onDetachedFromActivityForConfigChanges() {
activity = null
}
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
activity = binding.activity
}
override fun onDetachedFromActivity() {
activity = null
}
}
3. Dart 代码调用
最后,在你的Dart代码中,你可以使用 MethodChannel
来调用这些平台特定的实现。例如,在你的Flutter应用中:
// main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'my_plugin_interface.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
static const platform = MethodChannel('com.example.my_plugin');
static late MyPluginInterface _myPlugin;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin Demo'),
),
body: Center(
child: FutureBuilder<String>(
future: _getPlatformInfo(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return Text('Platform: ${snapshot.data}');
}
} else {
return CircularProgressIndicator();
}
},
),
),
),
);
}
Future<String> _getPlatformInfo() async {
// 这里你可以实例化你的插件接口,但在这个例子中我们直接使用MethodChannel
String platformInfo;
try {
platformInfo = await platform.invokeMethod('getPlatformInfo');
} on PlatformException catch (e) {
platformInfo = "Failed to get platform info: '${e.message}'.";
}
return platformInfo;
}
}
注意,在这个示例中,我们直接在Dart代码中使用了 MethodChannel
来调用平台特定的方法。在更复杂的情况下,你可能需要在Dart中实例化一个实现了 MyPluginInterface
的具体类,该类内部使用 MethodChannel
来与原生代码通信。
这个示例展示了如何在Flutter插件中使用 plugin_platform_interface
来定义和实现跨平台的接口。通过这种方式,你可以确保你的插件在不同平台上具有一致的API,同时允许平台特定的实现。