完整流程 Flutter 集成 Golang 多语言跨端开发基础案例

4,302 阅读1分钟

使用Golang一处编写,横跨中Android & IOS 多端场景使用。golang提供gomobile跨平台开发库,我们可快速编译可直接Android & IOS 原生调用的SDK包,借助这一优势,可更加方便使用,白哪个比较Rust需要使用FFI转化调用更加方便。

本文主要介绍了Flutter 集成Golang,所以并不会在Flutter、Golang等开发环境搭建以及Dart、go语言上做介绍,本次使用VSCode作为编辑器。

考虑Android & IOS 同时演示效果,所以本文使用MacOS系统作为演示,如仅仅需做安卓上测试可跳过相关IOS的配置等操作。

本地环境

Flutter版本

Golang版本

Golang环境

从官网下载go安装包 golang.google.cn/dl/ 解压到本地,这里安装存放到 /usr/local/go 目录下

  • GOPATH: go工作区, 即编写代码存放的目录
  • GOROOT: go的安装目录
  • GOPATH工作区目录下, 一般有3个目录, 分别是
  • bin: 存储可执行bin文件
  • pkg: 编译完成的文件
  • src: 源代码文件
wget -c  https://golang.google.cn/dl/go1.18.3.darwin-arm64.tar.gz

sudo tar -xzvf go1.18.3.darwin-arm64.tar.gz -C /usr/local
cd /usr/local/go

code ~/.bash_profile

# 增加如下几行 到 .bash_profile
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
export GO111MODULE=on
export GOPROXY=https://goproxy.cn

# 添加 ~/.bash_profile 后保存
code ~/.zshrc
source ~/.bash_profile

# 执行让环境变量生效
source ~/.zshrc

mkdir -p $GOPATH/src
mkdir -p $GOPATH/bin
mkdir -p $GOPATH/pkg

Golang 内容相关

创建项目

cd $GOPATH/src
mkdir demo
go mod init demo

编写案例

创建 greeting.go 文件,并编写如下内容,中后面调用时候传入内容并返回传入内容结果,以便演示数据互相传递

安装gomobile并初始化

gomobile init 初始化失败,请查看 完整流程 Flutter 集成 Rust 多语言跨端开发基础案例 中配置NDK相关内容配置好NDK之后,在执行 gomobile init

go get golang.org/x/mobile/cmd/gomobile
gomobile init

构建多平台SDK

Android

gomobile bind -target=android

IOS

gomobile bind -target=ios

构建后结果

构建后得到如图Android与IOS两个SDK文件

Flutter 内容相关

创建Flutter插件

这里直接使用Android Studio创建插件,也可以使用vscode或命令方式创建插件

导入Golang生成的SDK

将golang项目构建出的Android与IOS平台SDK导入 Flutter 插件项目各种目录中

导入 Android 所需SDK 至 android/libs 目录下,首次需要创建libs目录。导入完成后目录图如下

导入 IOS 所需SDK 到 ios/Frameworks 目录下,首次需要创建Frameworks目录。导入完成后目录如下图所示

这里要注意的是 构建出 IOS SDK 目录Greeting.xcframework中有两个

我们导入 ios-arm64_x86_64-simulator 目录下的 Greeting.framework 

Android 调用SDK

打开android目录下build.gradle,添加引用SDK

project插件项目名称,file指定目录

打开 src/main/kotlin/com/example/demo/GomobileDemoPlugin.kt 文件,增加如下判断,调用golang sdk

IOS 调用SDK

修改 demo.podspec 添加引用SDK

打开 ios/Classes/SwiftGomobileDemoPlugin.swift 文件增加如下判断,调用golang sdk

由于这边Flutter 版本是3.0.2,生成插件分三个文件,旧版本是一个,为方便演示,不做目录结构修改,这里修改lib三个文件调用,由于难度较低,这里直接贴上修改后结果

gomobile_demo.dart

import 'gomobile_demo_platform_interface.dart';

class GomobileDemo {
  Future<String?> getPlatformVersion() {
    return GomobileDemoPlatform.instance.getPlatformVersion();
  }

  Future<String?> getSayHi(String text) {
    return GomobileDemoPlatform.instance.getSayHi(text);
  }
}

gomobile_demo_method_channel.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import 'gomobile_demo_platform_interface.dart';

/// An implementation of [GomobileDemoPlatform] that uses method channels.
class MethodChannelGomobileDemo extends GomobileDemoPlatform {
  /// The method channel used to interact with the native platform.
@visibleForTesting
  final methodChannel = const MethodChannel('gomobile_demo');

  @override
  Future<String?> getPlatformVersion() async {
    final version =
        await methodChannel.invokeMethod<String>('getPlatformVersion');
    return version;
  }

  @override
  Future<String?> getSayHi(String text) async {
    final sayHi = await methodChannel.invokeMethod<String>(
      'getSayHi',
      {"text": text},
    );
    return sayHi;
  }
}

gomobile_demo_platform_interface.dart

import 'package:plugin_platform_interface/plugin_platform_interface.dart';

import 'gomobile_demo_method_channel.dart';

abstract class GomobileDemoPlatform extends PlatformInterface {
  /// Constructs a GomobileDemoPlatform.
GomobileDemoPlatform() : super(token: _token);

  static final Object _token = Object();

  static GomobileDemoPlatform _instance = MethodChannelGomobileDemo();

  /// The default instance of [GomobileDemoPlatform] to use.
 ///
 /// Defaults to [MethodChannelGomobileDemo].
static GomobileDemoPlatform get instance => _instance;

  /// Platform-specific implementations should set this with their own
 /// platform-specific class that extends [GomobileDemoPlatform] when
 /// they register themselves.
static set instance(GomobileDemoPlatform instance) {
    PlatformInterface.verifyToken(instance, _token);
    _instance = instance;
  }

  Future<String?> getPlatformVersion() {
    throw UnimplementedError('platformVersion() has not been implemented.');
  }

  Future<String?> getSayHi(String text) {
    throw UnimplementedError('platformVersion() has not been implemented.');
  }
}D

修改插件example调用测试

打开example中main.dart 文件,将如下代码直接复制全部替换,这些都是基础内容,看不明白可以去flutter官网或者查阅相关基础教程

import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:gomobile_demo/gomobile_demo.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';
  String _sayHi = 'Unknown';
  final _gomobileDemoPlugin = GomobileDemo();

  @override
  void initState() {
    super.initState();
    initPlatformState();
    initSayHiState();
  }

  Future<void> initPlatformState() async {
    String platformVersion;
    try {
      platformVersion = await _gomobileDemoPlugin.getPlatformVersion() ??
          'Unknown platform version';
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }
    if (!mounted) return;
    setState(() {
      _platformVersion = platformVersion;
    });
  }

  Future<void> initSayHiState() async {
    String sayHi;
    try {
      sayHi = await _gomobileDemoPlugin.getSayHi('你好') ??
          'Unknown platform version';
    } on PlatformException {
      sayHi = 'Failed to get platform version.';
    }
    if (!mounted) return;
    setState(() {
      _sayHi = sayHi;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Column(
            children: [
              Text('Running on: $_platformVersion\n'),
              Text('Hi: $_sayHi\n'),
            ],
          ),
        ),
      ),
    );
  }
}

效果图