Flutter 将数据从颤振传递到SwiftUI主屏幕WidgetExtension?访问SQLite数据库本身还是使用methodchannel?

Flutter 将数据从颤振传递到SwiftUI主屏幕WidgetExtension?访问SQLite数据库本身还是使用methodchannel?,flutter,swiftui,sqflite,Flutter,Swiftui,Sqflite,我有一个flatter应用程序,它使用SQFLite保存数据。我有兴趣尝试做一个iOS主屏幕小部件,根据我所收集的信息,它必须在swiftui中构建。我想知道是否可以从Swiftui中的本机小部件访问我的Flatter sqlite数据库 更新:尝试使用以下建议,但遇到问题。由于如果我将appdelegate模块添加为共享目标,小部件扩展似乎会导致xcode构建失败……我正试图将其跳转到swift文件调用,然后共享它。但是我遇到了错误 我的颤振助手(它目前只是尝试从一个列表中发送一个整数,或多或

我有一个flatter应用程序,它使用SQFLite保存数据。我有兴趣尝试做一个iOS主屏幕小部件,根据我所收集的信息,它必须在swiftui中构建。我想知道是否可以从Swiftui中的本机小部件访问我的Flatter sqlite数据库

更新:尝试使用以下建议,但遇到问题。由于如果我将appdelegate模块添加为共享目标,小部件扩展似乎会导致xcode构建失败……我正试图将其跳转到swift文件调用,然后共享它。但是我遇到了错误

我的颤振助手(它目前只是尝试从一个列表中发送一个整数,或多或少作为概念证明)

我称之为widgetSwift的Hop文件

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:


本文可以帮助您进行更详细的解释。

欢迎使用堆栈溢出。请按照建议添加您的搜索/研究工作的简要说明、代码和错误。我已在上面添加了尝试代码,但在获取这些代码时遇到了一些问题。你有什么想法吗?谢谢你试过这个吗?这让我得到了一个可以工作的小部件。:)@埃夫里皮德斯基里亚库