Flutter跨链桥接插件flutter_nekoton_bridge的使用
Flutter跨链桥接插件flutter_nekoton_bridge的使用
本指南将帮助你了解如何在Flutter项目中使用flutter_nekoton_bridge
插件。该插件基于flutter_rust_bridge
生成器,允许你在Flutter应用中与Rust代码进行交互。
安装
首先,在你的pubspec.yaml
文件中添加flutter_nekoton_bridge
依赖:
dependencies:
flutter_nekoton_bridge:
日志记录
在使用flutter_nekoton_bridge
之前,你需要设置日志记录。推荐使用logging
包来记录日志。以下是一个示例:
import 'package:logging/logging.dart';
import 'package:flutter_nekoton_bridge/flutter_nekoton_bridge.dart';
// 创建一个日志级别映射
static final Map<Level, fnb.LogLevel?> _logMap = {
Level.ALL: fnb.LogLevel.Trace,
Level.FINEST: fnb.LogLevel.Trace,
Level.FINER: fnb.LogLevel.Trace,
Level.FINE: fnb.LogLevel.Debug,
Level.CONFIG: fnb.LogLevel.Debug,
Level.INFO: fnb.LogLevel.Info,
Level.WARNING: fnb.LogLevel.Warn,
Level.SEVERE: fnb.LogLevel.Error,
Level.SHOUT: fnb.LogLevel.Error,
Level.OFF: null,
};
Level _toLogLevel(fnb.LogLevel level) {
return _logMap.keys.firstWhere((key) => _logMap[key] == level);
}
// 日志处理器
void _logHandler(fnb.LogEntry logEntry) {
final logLevel = _toLogLevel(logEntry.level);
_log.log(logLevel, '${logEntry.tag}: ${logEntry.msg}');
}
// 初始化日志记录
void setupLogger() {
Logger.root.level = Level.ALL; // 设置默认日志级别
Logger.root.onRecord.listen(_logHandler); // 设置日志处理器
}
桥接初始化
在日志记录之后,你需要调用initRustToDartCaller
函数来初始化桥接:
fnb.initRustToDartCaller();
桥接使用
固定点数
尽管我们在大多数情况下不使用scale
,但建议在应用中使用Fixed
包来处理固定点数。例如:
Fixed.fromInt(1234, scale: 3); // == 1.234
Fixed.fromBigInt(BigInt.from(1234), scale: 3); // == 1.234
final t1 = Fixed.fromDecimal(Decimal.fromInt(1), scale: 2); // == 1.00
final t3 = Fixed.parse('1.234', scale: 2); // == 1.23, scale: 2
金钱计算
我们推荐使用money2
包来进行货币计算。例如:
import 'package:money2/money2.dart';
Money usd = Money.fromDouble('USD', 12.5);
print(usd.toString()); // 输出 "12.50 USD"
示例代码
以下是一个完整的示例代码,展示了如何在Flutter项目中使用flutter_nekoton_bridge
插件:
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_nekoton_bridge/flutter_nekoton_bridge.dart';
Future<void> main() async {
await NekotonBridge.init();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late int sumResult;
late Future<int> sumAsyncResult;
String? fromMyClass;
[@override](/user/override)
void initState() {
super.initState();
sumResult = simpleAdderSync(a: 1, b: 2);
sumAsyncResult = simpleAdder(a: 3, b: 4);
// 这个设置不应该被移除或修改,因为它用于集成测试
setupLogger(
level: LogLevel.trace,
mobileLogger: false,
logHandler: (logEntry) => debugPrint(
'FromLib: ${logEntry.level} ${logEntry.tag} ${logEntry.msg} (lib_time=${logEntry.timeMillis})',
),
);
}
void _onPressed() async {
fromMyClass = await queryMyClass();
setState(() {});
}
void _onPressedLog() async {
debugPrint('Log!');
simpleLog(string: 'From dart: ${DateTime.now().toIso8601String()}');
}
void _onPressedPanic() async {
debugPrint('Panic!');
simplePanic();
}
// 缓存实例
CallerWrapper? _caller;
void _onPressedInitDartCaller() async {
initRustToDartCaller();
_caller = initCallerWrapper(CallerImpl());
}
List<CallerTestClassWrapper> testCallers = [];
void _onPressedAddTestCaller() async {
testCallers.add(await initCallerTestClassWrapper(Random().nextInt(1000)));
setState(() {});
}
void _onPressedTriggerTestCallers() {
for (var c in testCallers) {
c.caller.callSomeFunc();
}
}
void _onPressedDartCallFunc0(bool needResult) async {
simpleCallFunc0(needResult: needResult);
}
void _onPressedDartCallFunc1(bool needResult) async {
simpleCallFunc1(needResult: needResult);
}
void _onPressedDartCallFunc2() async {
simpleCallFunc2();
}
void _onPressedDartCallFunc3() async {
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
simpleCallFunc3();
}
// 这些按钮(带有*Test*回调)不应该被移除或修改,因为它们用于集成测试
void _onPressedTestInfo() async {
testLoggerInfo(string: 'test logger: info');
}
void _onPressedTestDebug() async {
testLoggerDebug(string: 'test logger: debug');
}
void _onPressedTestWarn() async {
testLoggerWarn(string: 'test logger: warn');
}
void _onPressedTestError() async {
testLoggerError(string: 'test logger: error');
}
void _onPressedTestPanic() async {
testLoggerPanic(string: 'test logger: panic');
}
void _testCallerCallTest0Async(bool needResult) async {
final result = await testCallerCallTest0Async(
string: 'testCallerCallTest0Async $needResult',
needResult: needResult,
);
debugPrint('result ${result.toDynamic()}');
}
void _testCallerCallTest0Sync(bool needResult) {
final result = testCallerCallTest0Sync(
string: 'testCallerCallTest0Sync $needResult',
needResult: needResult,
);
debugPrint('result ${result.toDynamic()}');
}
void _testCallerCallTest1Async(bool needResult) async {
final futures = <Future<DynamicValue>>[];
for (int i = 0; i < 7; i++) {
futures.add(testCallerCallTest1Async(
string: 'testCallerCallTest1Async $needResult',
needResult: needResult,
));
}
final results = await Future.wait(futures);
for (var result in results) {
debugPrint('result ${result.toDynamic()}');
}
}
[@override](/user/override)
Widget build(BuildContext context) {
const textStyle = TextStyle(fontSize: 25);
const spacerSmall = SizedBox(height: 10);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Native Packages'),
),
body: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(10),
child: Column(
children: [
const Text(
'logger-related',
style: textStyle,
),
Wrap(
children: [
TextButton(
onPressed: () => _onPressedTestInfo(),
child: const Text('i'),
),
TextButton(
onPressed: () => _onPressedTestDebug(),
child: const Text('d'),
),
TextButton(
onPressed: () => _onPressedTestWarn(),
child: const Text('w'),
),
TextButton(
onPressed: () => _onPressedTestError(),
child: const Text('e'),
),
TextButton(
onPressed: () => _onPressedTestPanic(),
child: const Text('p'),
),
],
),
const Text(
'caller-related',
style: textStyle,
),
Wrap(
children: [
TextButton(
onPressed: _onPressedInitDartCaller,
child: const Text('initDartCaller'),
),
TextButton(
onPressed: () => _testCallerCallTest0Async(false),
child: const Text('Test0Async'),
),
TextButton(
onPressed: () => _testCallerCallTest0Async(true),
child: const Text('Test0AsyncResult'),
),
TextButton(
onPressed: () => _testCallerCallTest0Sync(false),
child: const Text('Test0Sync'),
),
TextButton(
onPressed: () => _testCallerCallTest0Sync(true),
child: const Text('Test0SyncResult'),
),
TextButton(
onPressed: () => _testCallerCallTest1Async(true),
child: const Text('Test1AsyncResult'),
),
],
),
Text(
'sum(1, 2) = $sumResult',
style: textStyle,
textAlign: TextAlign.center,
),
spacerSmall,
FutureBuilder<int>(
future: sumAsyncResult,
builder: (BuildContext context, AsyncSnapshot<int> value) {
final displayValue = (value.hasData) ? value.data : 'loading';
return Text(
'await sumAsync(3, 4) = $displayValue',
style: textStyle,
textAlign: TextAlign.center,
);
},
),
TextButton(
onPressed: _onPressed,
child: Text('From MyClass $fromMyClass'),
),
TextButton(
onPressed: _onPressedLog,
child: const Text('Log'),
),
TextButton(
onPressed: _onPressedPanic,
child: const Text('Panic'),
),
TextButton(
onPressed: () => _onPressedDartCallFunc0(true),
child: const Text('CallFunc0 WITH result'),
),
TextButton(
onPressed: () => _onPressedDartCallFunc1(true),
child: const Text('CallFunc1 WITH result'),
),
TextButton(
onPressed: () => _onPressedDartCallFunc0(false),
child: const Text('CallFunc0 WITHOUT result'),
),
TextButton(
onPressed: () => _onPressedDartCallFunc1(false),
child: const Text('CallFunc1 WITHOUT result'),
),
TextButton(
onPressed: () => _onPressedDartCallFunc2(),
child: const Text('CallFunc2'),
),
TextButton(
onPressed: () => _onPressedAddTestCaller(),
child: const Text('Add test caller'),
),
TextButton(
onPressed: () => _onPressedTriggerTestCallers(),
child: const Text('Trigger test callers'),
),
TextButton(
onPressed: () => _onPressedDartCallFunc3(),
child: const Text('CallFunc3'),
),
],
),
),
),
),
);
}
}
更多关于Flutter跨链桥接插件flutter_nekoton_bridge的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter跨链桥接插件flutter_nekoton_bridge的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用Flutter跨链桥接插件flutter_nekoton_bridge
的示例代码案例。这个示例假定你已经有一个Flutter项目,并且已经添加了flutter_nekoton_bridge
插件到你的pubspec.yaml
文件中。
1. 添加依赖
首先,确保你的pubspec.yaml
文件中包含以下依赖:
dependencies:
flutter:
sdk: flutter
flutter_nekoton_bridge: ^latest_version # 替换为最新的版本号
然后运行flutter pub get
来安装依赖。
2. 导入包
在你的Dart文件中导入flutter_nekoton_bridge
包:
import 'package:flutter_nekoton_bridge/flutter_nekoton_bridge.dart';
3. 初始化插件
在你的应用的主文件(通常是main.dart
)中初始化flutter_nekoton_bridge
插件。
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化 flutter_nekoton_bridge 插件
NekotonBridge.initialize();
runApp(MyApp());
}
4. 使用跨链桥接功能
下面是一个简单的例子,展示如何使用flutter_nekoton_bridge
插件进行跨链操作。这里假设你需要从一个链传输资产到另一个链。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Nekoton Bridge Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
try {
// 示例参数,你需要根据实际情况调整
String fromChainId = 'your_from_chain_id';
String toChainId = 'your_to_chain_id';
String assetId = 'your_asset_id';
String amount = 'your_amount';
String recipientAddress = 'recipient_address';
// 调用跨链传输函数
var result = await NekotonBridge.transferAsset(
fromChainId: fromChainId,
toChainId: toChainId,
assetId: assetId,
amount: amount,
recipientAddress: recipientAddress,
);
// 处理结果
print('Transfer result: $result');
} catch (e) {
// 处理错误
print('Error during transfer: $e');
}
},
child: Text('Transfer Asset'),
),
),
),
);
}
}
注意事项
- 链ID和资产ID:在实际应用中,你需要根据目标链和资产的实际ID来替换示例代码中的
fromChainId
、toChainId
、assetId
等参数。 - 用户授权:跨链传输通常需要用户授权,这个示例没有包含授权逻辑,你需要根据插件的文档和用户界面需求来添加。
- 错误处理:在实际应用中,错误处理会更加复杂,你可能需要更详细的错误分类和处理逻辑。
这个示例提供了一个基本的框架,你可以根据具体的需求和插件的API文档来扩展和完善功能。