美文网首页Flutter
Flutter与Go交互

Flutter与Go交互

作者: h2coder | 来源:发表于2023-07-27 23:23 被阅读0次

效果演示

Flutter与Go交互.jpg

使用 go mobile 打包Android依赖库

创建go工程目录

  • 目录名:go-calc

初始化go模块

  • 开启 go modules功能
go env -w GO111MODULE=on
  • 在项目根目录下,初始化go modules,执行完后,目录中会生成一个go.mod文件
go mod init 工程目录名

安装 go mobile

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

编译 go mobile

go build golang.org/x/mobile/cmd/gomobile

初始化 go mobile 环境

gomobile init

编写 go 代码

  • 在工程目录下,创建一个calc目录,用于存放go代码
  • 代码很简单,提供了一个Calc函数,传入2个int整形参数,相加后返回
  • 注意:go的函数,首字母代码代表是公共方法,首字母小写则是私有方法,这里需要暴露方法出来给JNI调用,所以函数名的首字母必须是大写,否则后面的编译aar操作时,命令执行会报错,提示找不到函数!
package calc

/*
   计算
*/
func Calc(x int, y int) int {
    return x + y
}

编译 go 代码 为 安卓 aar 文件

  • 编译时间可能需要2 ~ 3分钟,需要耐心等待
  • 命令执行完后,会生成2个文件,分别是calc.aarcalc-sources.jar,我们需要导入aar文件
# 注意gomobile可执行文件在根目录,在根目录下执行bind命令,后面跟着go代码的目录
./gomobile bind ./calc/
# 或者直接去到go代码目录,执行命令
../gomobile bind

Flutter工程,依赖go生成的aar依赖库

添加依赖库

  • 切换到Flutter的Android工程目录,找到app目录下的libs目录,将aar放进去
  • app目录下的build.gradle,添加依赖配置
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    //引用libs下的aar文件
    implementation(fileTree("libs"))
}

编写Android与Flutter通信代码

  • Go生成的JNI类为Calc.java,我们的go计算函数会映射为java的calc静态方法,所以调用比较简单,只需要val calcResult = Calc.calc(x, y)即可
class MainActivity : FlutterActivity() {
    companion object {
        /**
         * 原生和Flutter交互的通道名
         */
        const val CHANNEL_NAME = "channel_flutter_go"
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GeneratedPluginRegistrant.registerWith(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_NAME)
            .setMethodCallHandler { call, result ->
                // 判断是计算方法,才执行对应逻辑
                if (call.method.equals("calc")) {
                    val x = call.argument<Any>("x")?.toString()?.toLong() ?: 0
                    val y = call.argument<Any>("y")?.toString()?.toLong() ?: 0
                    // 调用Go,进行计算
                    val calcResult = Calc.calc(x, y)
                    result.success(calcResult)
                } else {
                    // 找不到指定方法
                    result.notImplemented()
                }
            }
    }
}

编写Flutter页面,并于Android通信

主程序

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

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

/// 主页面
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Go',
      theme: ThemeData(
        //主题色
        primarySwatch: Colors.blue,
        //colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        //是否使用Material3风格
        useMaterial3: false,
      ),
      home: const HomePage(title: 'Flutter Go'),
    );
  }
}

首页

  • 通过MethodChannel,调用Android提供的方法,而在Android提供的方法中,调用Go的JNI函数
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_go/util/toast_util.dart';

/// 首页
class HomePage extends StatefulWidget {
  const HomePage({super.key, required this.title});

  /// 页面标题
  final String title;

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  /// 原生和Flutter交互的通道名
  static const channelName = "channel_flutter_go";

  final TextEditingController _number1EditingController =
      TextEditingController(text: "1");
  final TextEditingController _number2EditingController =
      TextEditingController(text: "2");
  final TextEditingController _resultEditingController =
      TextEditingController(text: "0");

  /// 调用Go的方法
  Future<int> _callGoMethod(int x, int y) async {
    const channel = MethodChannel(channelName);
    // 参数
    var args = {};
    args['x'] = x;
    args['y'] = y;
    return await channel.invokeMethod<int>('calc', args) ?? 0;
  }

  /// 处理计算
  void _handleCalc() async {
    var num1Str = _number1EditingController.text.trim();
    var num2Str = _number2EditingController.text.trim();
    if (num1Str.isEmpty) {
      ToastUtil.toast("请输入第1个数字");
      return;
    }
    if (num2Str.isEmpty) {
      ToastUtil.toast("请输入第2个数字");
      return;
    }
    // 调用Go的方法
    var result = await _callGoMethod(int.parse(num1Str), int.parse(num2Str));
    ToastUtil.toast("计算成功");
    _resultEditingController.text = result.toString();
  }

  /// 构建数字文本输入框
  Widget _buildTextField(TextEditingController controller) {
    return Expanded(
      child: TextField(
        textAlign: TextAlign.center,
        controller: controller,
        // 最大行数
        maxLines: 1,
        //设置进入页面是否自动弹出键盘
        autofocus: false,
        // 设置键盘为数字
        keyboardType: TextInputType.number,
        inputFormatters: [
          // 设置只允许输入数字
          FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
          // 输入字符的长度限制
          LengthLimitingTextInputFormatter(10)
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.primary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 10.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              _buildTextField(_number1EditingController),
              Container(
                margin: const EdgeInsets.all(10),
                child: const Text("+"),
              ),
              _buildTextField(_number2EditingController),
              Container(
                margin: const EdgeInsets.symmetric(horizontal: 10),
                child: ElevatedButton(
                  child: const Text("="),
                  onPressed: () async {
                    _handleCalc();
                  },
                ),
              ),
              _buildTextField(_resultEditingController)
            ],
          ),
        ),
      ),
    );
  }
}

相关文章

网友评论

    本文标题:Flutter与Go交互

    本文链接:https://www.haomeiwen.com/subject/uierpdtx.html