Flutter 将数据从颤振传递到SwiftUI主屏幕WidgetExtension?访问SQLite数据库本身还是使用methodchannel?
我有一个flatter应用程序,它使用SQFLite保存数据。我有兴趣尝试做一个iOS主屏幕小部件,根据我所收集的信息,它必须在swiftui中构建。我想知道是否可以从Swiftui中的本机小部件访问我的Flatter sqlite数据库 更新:尝试使用以下建议,但遇到问题。由于如果我将appdelegate模块添加为共享目标,小部件扩展似乎会导致xcode构建失败……我正试图将其跳转到swift文件调用,然后共享它。但是我遇到了错误 我的颤振助手(它目前只是尝试从一个列表中发送一个整数,或多或少作为概念证明) 我称之为widgetSwift的Hop文件Flutter 将数据从颤振传递到SwiftUI主屏幕WidgetExtension?访问SQLite数据库本身还是使用methodchannel?,flutter,swiftui,sqflite,Flutter,Swiftui,Sqflite,我有一个flatter应用程序,它使用SQFLite保存数据。我有兴趣尝试做一个iOS主屏幕小部件,根据我所收集的信息,它必须在swiftui中构建。我想知道是否可以从Swiftui中的本机小部件访问我的Flatter sqlite数据库 更新:尝试使用以下建议,但遇到问题。由于如果我将appdelegate模块添加为共享目标,小部件扩展似乎会导致xcode构建失败……我正试图将其跳转到swift文件调用,然后共享它。但是我遇到了错误 我的颤振助手(它目前只是尝试从一个列表中发送一个整数,或多或
import Foundation
@objc class WidgetData: NSObject{
public func getWidgetData(result: Int)-> Int {
var x = -1
let a = UIApplication.shared.delegate as! AppDelegate
a.getTasks(args: "getDataFromFlutter", completion: {(result) -> Int in
x = result
})
return x
// let x = AppDelegate.getTasks(<#T##self: AppDelegate##AppDelegate#>);
}
}
<代码>导入基础
@objc类WidgetData:NSObject{
公共函数getWidgetData(结果:Int)->Int{
变量x=-1
将a=UIApplication.shared.delegate设为!AppDelegate
a、 getTasks(args:“GetDataFromFlatter”,完成:{(结果)->Int in
x=结果
})
返回x
//设x=AppDelegate.getTasks();
}
}
我的widget扩展部分调用它
struct widget_extension_widgetEntryView : View {
var entry: Provider.Entry
var body: some View {
let w = WidgetData()
let x: Int = w.getWidgetData(result: <#Int#>)
let str = "Today's Tasks: \(x)"
Text("", tableName: str)
}
}
struct小部件\u扩展\u widgetEntryView:View{
var条目:Provider.entry
var body:一些观点{
设w=WidgetData()
设x:Int=w.getWidgetData(结果:)
让str=“今天的任务:\(x)”
文本(“,表名:str)
}
}
扩展名给出了源文件中函数调用的错误:编辑器占位符
widgetSwift在getTasks调用中提供错误:
在作用域中找不到“AppDelegate”
声明的关闭结果“()”与上下文类型“Int”不兼容。颤振提供了一种使用
MethodChannel
与本机平台代码通信的方法
从颤振MethodChannel
文档():
Flatter使用灵活的系统,允许您调用特定于平台的API,无论是Android上的Kotlin或Java代码,还是iOS上的Swift或Objective-C代码
注意:如果需要,方法调用也可以反向发送,平台充当Dart中实现的方法的客户端。插件就是一个具体的例子
MethodChannel
从flatter调用本机平台代码上的函数的用法:
static final channelName = 'com.example.widget/database';
final methodChannel = MethodChannel(channelName);
await this.methodChannel.invokeMethod("getDataFromDatabase");
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.example.widget/database";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("getDataFromDatabase")) {
//TODO: Perform method to query database here
String data;
if (data != null) {
result.success(data);
} else {
result.error("UNAVAILABLE", "Data not available", null);
}
} else {
result.notImplemented();
}
}
);
}
}
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "com.example.widget/database",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "getDataFromDatabase" else {
result(FlutterMethodNotImplemented)
return
}
//TODO: Perform method to query database here
let data;
if data == nil {
result(FlutterError(code: "UNAVAILABLE",
message: "Data not available",
details: nil))
} else {
result(data)
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
我们在flatter、iOS和Android中创建一个同名的方法通道对象。Android和iOS对象将设置一个方法调用处理程序来接收来自Flatter的调用。然后,flatter代码可以调用invokeMethod来调用本机对象上的处理程序
颤振:
static final channelName = 'com.example.widget/database';
final methodChannel = MethodChannel(channelName);
await this.methodChannel.invokeMethod("getDataFromDatabase");
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.example.widget/database";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("getDataFromDatabase")) {
//TODO: Perform method to query database here
String data;
if (data != null) {
result.success(data);
} else {
result.error("UNAVAILABLE", "Data not available", null);
}
} else {
result.notImplemented();
}
}
);
}
}
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "com.example.widget/database",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "getDataFromDatabase" else {
result(FlutterMethodNotImplemented)
return
}
//TODO: Perform method to query database here
let data;
if data == nil {
result(FlutterError(code: "UNAVAILABLE",
message: "Data not available",
details: nil))
} else {
result(data)
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Android:
static final channelName = 'com.example.widget/database';
final methodChannel = MethodChannel(channelName);
await this.methodChannel.invokeMethod("getDataFromDatabase");
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.example.widget/database";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("getDataFromDatabase")) {
//TODO: Perform method to query database here
String data;
if (data != null) {
result.success(data);
} else {
result.error("UNAVAILABLE", "Data not available", null);
}
} else {
result.notImplemented();
}
}
);
}
}
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "com.example.widget/database",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "getDataFromDatabase" else {
result(FlutterMethodNotImplemented)
return
}
//TODO: Perform method to query database here
let data;
if data == nil {
result(FlutterError(code: "UNAVAILABLE",
message: "Data not available",
details: nil))
} else {
result(data)
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
iOS:
static final channelName = 'com.example.widget/database';
final methodChannel = MethodChannel(channelName);
await this.methodChannel.invokeMethod("getDataFromDatabase");
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.example.widget/database";
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("getDataFromDatabase")) {
//TODO: Perform method to query database here
String data;
if (data != null) {
result.success(data);
} else {
result.error("UNAVAILABLE", "Data not available", null);
}
} else {
result.notImplemented();
}
}
);
}
}
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "com.example.widget/database",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
// Note: this method is invoked on the UI thread.
guard call.method == "getDataFromDatabase" else {
result(FlutterMethodNotImplemented)
return
}
//TODO: Perform method to query database here
let data;
if data == nil {
result(FlutterError(code: "UNAVAILABLE",
message: "Data not available",
details: nil))
} else {
result(data)
}
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
反向示例–从本机调用颤振
如果您需要从本机代码调用在flatter中定义的方法,那么您可以从前面调用相同的方法,但这次您在flatter端调用setMethodCallHandler
,在本机端调用invokeMethod
颤振:
final channelName = 'dataFromFlutterChannel';
final methodChannel = MethodChannel(channelName);
methodChannel.setMethodCallHandler(this._handleMethod);
Future<void> _handleMethod(MethodCall call) async {
final String utterance = call.arguments;
switch(call.method) {
case "getDataFromFlutter":
//TODO: Query database here and return the data to native side
}
}
iOS:
本文可以帮助您进行更详细的解释。欢迎使用堆栈溢出。请按照建议添加您的搜索/研究工作的简要说明、代码和错误。我已在上面添加了尝试代码,但在获取这些代码时遇到了一些问题。你有什么想法吗?谢谢你试过这个吗?这让我得到了一个可以工作的小部件。:)@埃夫里皮德斯基里亚库