go-flutter开发桌面应用(五) go-flutter的Go端向Dart端发送消息

921 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言: 今天刚看到,可以【搬运自己的原创文章】参加“程序员必备小知识”活动,十分激动。 想起来之前在某平台上还有几篇技术文章,觉着掘金技术氛围更浓厚,正想搬过来。

原文链接: go-flutter开发桌面应用(五) go-flutter的Go端向Dart端发送消息 - 知乎 (zhihu.com)

正文

对于go-flutter插件,有很多情况需要从Go端向Dart端发送消息,比如一些定时处理、异步处理。

如果只是Dart端的动作去调用go-flutter的插件里的函数,那就和传统的网页请求一样了,网页端发送请求,服务端返回响应在网页显示。

如果能在go-flutter的Go端的代码能向Dart端发送消息,就有些像是WebSocket了,实现双向发送消息。

go-flutter的Go端向Dart端发送消息,这个一开始实在是不知道怎么去调用。也和一个知乎好友的想法一样,曾经想着要不要用TCP去实现。但是个人对TCP又一点儿也不懂,遂放弃。

就在前几天,忽然想到这样的需求是很广泛的,go-flutter就该实现了才对,所以又在go-flutter的github仓库上一通找,然后在go-flutter的插件的wiki中找到了具体的用法。

也是通过消息通道来实现,Go端向消息通道发送消息,Dart端监听消息并处理。

相关代码(履历为 Go端向Dart端发送消息 的版本)

Go端代码(上面链接里的内容CV到此):

// Golang
channel := plugin.NewMethodChannel(messenger, "samples/demo", plugin.StandardMethodCodec{})
err := p.channel.InvokeMethod("test", nil)
// error handling..

Dart端代码(上面链接里的内容CV到此):

// Dart
const platform_channel = MethodChannel("samples/demo");
platform_channel.setMethodCallHandler((MethodCall methodCall) async {
  print(methodCall.method); // prints: test
});

官网文档(Github上go-flutter的插件的wiki)上还提供了一个Go端向Dart端发送完消息,等待Dart端响应结果的用法。

Go端代码(上面链接里的内容CV到此):

// Golang
channel := plugin.NewMethodChannel(messenger, "samples/demo", plugin.StandardMethodCodec{})
reply, err := channel.InvokeMethodWithReply("test", nil) // blocks the goroutine until reply is avaiable
// error handling..
spew.Dump(reply) // prints 5 seconds later: (string) (len=21) "reply from dart: test"

Dart端代码(上面链接里的内容CV到此):

// Dart
const platform_channel = MethodChannel("samples/demo");
platform_channel.setMethodCallHandler((MethodCall methodCall) async {
  print(methodCall.method); // prints: test
  await Future.delayed(Duration(seconds: 5));
  return "reply from dart: " + methodCall.method;
});

Go端发送完消息后等待Dart端响应结果的用法鄙人没有尝试,应该不难。
鄙人只试了下Go端向Dart端发送消息的用法,已添加到第一节的工程中。

GitHub - bettersun/hellogoflutter

具体机能是添加了一个从Go端向Dart端定时发送消息的处理。

主要代码:

Go端:

定义机能函数:

// 向Dart端发送消息(定时)
func sendInterval(channel *plugin.MethodChannel) {
	ticker := time.NewTicker(time.Second * 1)
	go func() {
		for _ = range ticker.C {
			fmt.Println("sendInterval")
			err := channel.InvokeMethod("interval", time.Now().Format("2006/01/02 15:04:05"))
			if err != nil {
				log.Println(err)
			}
		}
	}()
}

初始化插件时在新的goroutine里运行上面定义的机能函数。

// 初始化插件
func (HelloPlugin) InitPlugin(messenger plugin.BinaryMessenger) error {
	channel := plugin.NewMethodChannel(messenger, channelName, plugin.StandardMethodCodec{})
	channel.HandleFunc(hello, helloFunc)
	channel.HandleFunc(message, messageFunc)

	// 向Dart端发送消息
	go sendInterval(channel)

	return nil
}

Dart端:

在initState()添加对消息通道的监听。

参数的method是Go端发送过来的函数名。

参数的arguments是Go端发送过来的函数的返回值,类型是dynamic,需要根据具体类型进行解析。

class _HelloPageState extends State<HelloPage> {
  String timeNow = '';

  @override
  void initState() {
    // 监听Go端发过来的消息
    HelloPlugin.channel.setMethodCallHandler((MethodCall methodCall) async {
      if (methodCall.method == 'interval') {
        setState(() {
          print(methodCall.arguments);
          timeNow = methodCall.arguments;
        });
      }
    });

    super.initState();
  }

  // ...
}

运行结果如下,标题栏显示的时间是Go端发送过来的时间。

image.png