这是【Flutter 问题系列第 70 篇】,如果觉得有用的话,欢迎关注专栏。
博文所用 Flutter SDK:2.2.3,Dart SDK:2.13.4。
摘要:
因为有人注重结果,所以想直接把代码拿过来先运行下看效果,那么这篇博客就是为你量身打造的。
也有人看重过程,那么这篇 详细说明 Flutter 与 Android 原生交互(通信)方式之 MethodChannel(保姆级图文教程)值得你一看。
一:简述 Flutter 与原生通信的三种方式
Flutter 与原生通信有三种方式
- MethodChannel
- EventChannel
- BasicMessageChannel
这三种方式,无论是传递方法还是事件,本质上都是传递的数据。
二:Flutter 与 Android 原生通信
因为我在工作中用到最多的通信方式是 MethodChannel,后面我将以该方式为例,说下 Flutter 与 Android 原生是如何通信的,下面我们分端进行描述。
三:Flutter 端
先看示例代码
import 'dart:convert';
import 'package:flutter/services.dart';
// ------------------------------------------------------
// author:Allen Su
// date :2022/6/20 22:25
// usage :插件理器 - Flutter 端
// ------------------------------------------------------
class PackageManager {
// _channel 是通道的实例,package_manager 是自定义的通道名称
static const MethodChannel _channel = const MethodChannel("package_manager");
// 根据传入的包名安装 App
// 注:方法名install和invokeMethod中的参数install不是要一定相同,这里相同是为了方便一眼看出函数的功能
Future<bool> install() async {
// install 调用方法的名称,com.allensu 传递的数据
bool res = await _channel.invokeMethod("install", "com.allensu");
return res;
}
}
设置 Flutter 端的通道比较简单,一共需要两步
第 1 步:创建通道
在 Flutter 中,使用 MethodChannel
创建通道。有一个必传参数 name
,是通道起的名称,一个通道对应一个唯一的名称,不同的通道用了相同的名称会彼此干扰。
第 2 步:发起通道方法的调用
在 Flutter 端我们使用 MethodChannel 类中的方法 invokeMethod
发起一次调用。
invokeMethod 是一个返回值为泛型的异步方法(返回值根据需要设置,可有可无),有一个必传参数 method
,是要调用的方法的名称,还有一个可传参数 arguments
,是方法调用时传递的数据,类型是 dynamic 。
四:Android 端
先看示例代码
第一部分是关于具体要实现功能类的写法,如下代码所示
package com.package.manager.package_demo;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;
// ------------------------------------------------------
// author:suxing
// date :2022/6/20 22:40
// usage :插件理器 - Android 端
// ------------------------------------------------------
public class PackageManagerPlugin implements FlutterPlugin {
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
// 声明通道,第二个参数 name 要和 Flutter 中定义的通道名称保持一致
MethodChannel channel = new MethodChannel(binding.getBinaryMessenger(), "package_manager");
// 在此通道上注册方法调用将要处理的功能(函数)
channel.setMethodCallHandler(this::onMethodCall);
}
/// 处理不同名称方法的回调
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
// call.method 回调中的方法名,要和在 Flutter 中定义的保持一致
switch (call.method) {
case "install":
// 这里的 packageName 是在 Flutter 中定义的 com.allensu
String packageName = call.arguments();
// 执行安装功能,并返回安装结果
boolean res = install(packageName);
// 将安装结果回调给 Flutter
result.success(res);
break;
case "other":
// 这里的 other 是一个测试,意思是如果方法名是 other,则执行 doSomething 函数
doSomething();
// 如果不需要回调数据,则参数填 null
result.success(null);
break;
default:
// 如果回调异常,则设置相关信息
result.error("错误码","错误信息","错误详情");
break;
}
}
}
第二部分是在 MainActivity 中注册插件的实例,如下代码所示
package com.package.manager.package_demo;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngin e;
// ------------------------------------------------------
// author:Allen Su
// date :2022/6/20 22:45
// usage :Flutter 与 Android 通信的入口
// ------------------------------------------------------
public class MainActivity extends FlutterActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
// 注册插件的实例(如果有多个需要册插件的实例,依次增加即可)
flutterEngine.getPlugins().add(new PackageManagerPlugin());
super.configureFlutterEngine(flutterEngine);
}
}
设置 Android 端的通道相对麻烦一点,一共需要三步
第 1 步:创建通道
同样使用 MethodChannel 声明一个通道,特别要注意,第二个参数 name 要和 Flutter 中定义的通道名称保持一致。
第 2 步:在通道上注册方法
通过 channel.setMethodCallHandler 在通道上注册方法,通过 call.method 获取当前通信的方法名,通过 result.success 和 result.error 设置回调状态。
第 3 步:在 MainActivity 中注册插件的实例
通过 flutterEngine.getPlugins().add 方法注册插件的实例即可。
你的问题得到解决了吗?欢迎在评论区留言。
赠人玫瑰,手有余香,如果觉得文章不错,希望可以给个一键三连,感谢。
Google 的 Flutter 越来越火,截止 2022年6月21日 GitHub 标星已达 142K,Flutter 毅然是一种趋势,所以作为前端开发者,没有理由不趁早去学习。
结束语
无论你是 Flutter 新手还是已经入门了,不妨先点个关注,后续我会将 Flutter 中的常用组件(含有源码分析、组件的用法及注意事项)以及可能遇到的问题写到 CSDN 博客中,希望自己学习的同时,也可以帮助更多的人。