likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 21

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

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

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

本地环境

Flutter版本

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

Golang版本

完整流程 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 文件,并编写如下内容,中后面调用时候传入内容并返回传入内容结果,以便演示数据互相传递

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

安装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 集成 Golang 多语言跨端开发基础案例

Flutter 内容相关

创建Flutter插件

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

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

导入Golang生成的SDK

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

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

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

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

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

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

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

Android 调用SDK

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

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

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

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

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

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

IOS 调用SDK

修改 demo.podspec 添加引用SDK

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

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

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

由于这边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'),
            ],
          ),
        ),
      ),
    );
  }
}

效果图

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