如何在Dart和本机代码之间的Flutter中建立桥梁
Flutter允许我们调用Android上的Java或Kotlin代码以及iOS上的Objective C或Swift代码可用的平台特定的API。
Flutter的特定于平台的API可用于消息传递。
从Flutter应用程序中,我们必须通过平台通道将消息发送到该应用程序的iOS或Android部分上的主机。 主机在平台通道上侦听并接收消息。 然后,它将使用本机编程语言使用任何特定于平台的API,并将响应发送回应用程序的Flutter部分。
架构概述
消息使用平台通道在Flutter Code(UI)和主机(平台)之间传递。 消息和响应异步传递,并且用户界面保持响应。
在Dart端,使用MethodChannel(API)我们发送一条与方法调用相对应的消息。 在Android上,MethodChannel Android(API)和iOS上,FlutterMessageChannel(API)用于接收方法调用和发送回结果。 这些类使我们能够使用非常简单的代码来开发平台插件。
如果需要,方法调用也可以反向发送,而Android / IOS平台充当Dart中实现的客户端和方法。
平台渠道支持的数据类型
标准平台通道使用标准消息编解码器,该消息编解码器支持对简单的类JSON值(布尔值,数字,字符串,字节缓冲区,列表和映射)进行有效的二进制序列化。 当我们发送和接收值时,这些值与消息之间的序列化和反序列化会自动发生。
创建调用iOS和Android代码的Flutter应用
现在,我们将创建一个带有方法调用的flutter应用程序,该方法调用将分别在Android(Java)和iOS(Objective C)中实现。
1.创建一个新的应用程序项目
在终端运行中:
flutter创建flutter_to_native
默认情况下,Flutter支持在Java和iOS中使用Objective C编写Android代码。如果要使用Kotlin和Swift,请使用以下命令创建项目。
flutter create -i swift -a kotlin flutter_to_native
2.创建平台频道
通道的客户端和主机端通过在通道构造函数中传递的通道名称连接。 单个应用中使用的所有频道名称必须唯一。 在我们的示例中,我们正在创建频道名称flutter.native / helper
class _MyHomePageState extends State<MyHomePage> { static const platform = const MethodChannel( 'flutter.native/helper' );
3.在平台通道上调用方法
在方法通道上调用方法,并通过String标识符指定要调用的具体方法。 在下面的代码中,它是helloFromNativeCode
String response = "" ; try { final String result = await platform .invokeMethod( 'helloFromNativeCode' ); response = result; } on PlatformException catch (e) { response = "Failed to Invoke: ' ${e. message } '." ; }
使用返回的响应来更新setState中的用户界面状态。
setState(() { _responseFromNativeCode = response; });
4.使用Java在Android中创建方法实现
在Android Studio中,打开Flutter应用,然后选择其中的android文件夹。 打开文件MainActivity.java
现在,我们必须创建一个与在Flutter App中创建的名称相同的MethodChannel。
public class MainActivity extends FlutterActivity { private static final String CHANNEL = "flutter.native/helper" ;
我们必须在onCreate方法中创建MethodCallHandler
new MethodChannel(getFlutterView(), CHANNEL ).setMethodCallHandler( new MethodChannel.MethodCallHandler() { @Override public void onMethodCall(MethodCall call, MethodChannel.Result result) { if (call. method .equals( "helloFromNativeCode" )) { String greetings = helloFromNativeCode(); result.success(greetings); } }});
5.使用Objective C在iOS中创建方法实现
在Xcode中打开Flutter应用的文件AppDelegate.m。 现在,我们必须创建一个FlutterMethodChannel,其名称与在Flutter App中创建的名称相同。
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; FlutterMethodChannel* nativeChannel = [FlutterMethodChannel methodChannelWithName:@ "flutter.native/helper" binaryMessenger:controller];
创建方法调用处理程序
[nativeChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { if ([@ "helloFromNativeCode" isEqualToString:call.method]) { NSString *strNative = [weakSelf helloFromNativeCode]; result(strNative); } else { result(FlutterMethodNotImplemented); } }];
完整的代码
Android本机代码
import android.os.Bundle; import io.flutter.app.FlutterActivity; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity { private static final String CHANNEL = "flutter.native/helper" ; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); GeneratedPluginRegistrant. registerWith ( this ); new MethodChannel(getFlutterView(), CHANNEL ).setMethodCallHandler( new MethodChannel.MethodCallHandler() { @Override public void onMethodCall(MethodCall call, MethodChannel.Result result) { if (call. method .equals( "helloFromNativeCode" )) { String greetings = helloFromNativeCode(); result.success(greetings); } }}); }
public class MainActivity extends FlutterActivity { private static final String CHANNEL = "flutter.native/helper" ; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); GeneratedPluginRegistrant. registerWith ( this ); new MethodChannel(getFlutterView(), CHANNEL ).setMethodCallHandler( new MethodChannel.MethodCallHandler() { @Override public void onMethodCall(MethodCall call, MethodChannel.Result result) { if (call. method .equals( "helloFromNativeCode" )) { String greetings = helloFromNativeCode(); result.success(greetings); } }}); }
private String helloFromNativeCode() { return "Hello from Native Android Code" ; } }
private String helloFromNativeCode() { return "Hello from Native Android Code" ; } }
iOS本机代码
#include "AppDelegate.h" #include "GeneratedPluginRegistrant.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; FlutterMethodChannel* nativeChannel = [FlutterMethodChannel methodChannelWithName:@ "flutter.native/helper" binaryMessenger:controller]; __weak typeof(self) weakSelf = self; [nativeChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { if ([@ "helloFromNativeCode" isEqualToString:call.method]) { NSString *strNative = [weakSelf helloFromNativeCode]; result(strNative); } else { result(FlutterMethodNotImplemented); } }]; [GeneratedPluginRegistrant registerWithRegistry:self]; return [ super application:application didFinishLaunchingWithOptions:launchOptions]; } - (NSString *)helloFromNativeCode { return @ "Hello From Native IOS Code" ; } @end
颤动代码
import 'package:flutter/material.dart' ; import 'dart:async' ; import 'package:flutter/services.dart' ; void main() => runApp( new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( home: new HomePage(), ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: const Text( 'Native Code from Dart' ), ), body: new MyHomePage(), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this . title }) : super (key: key); final String title ; @override _MyHomePageState createState() => new _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { static const platform = const MethodChannel( 'flutter.native/helper' ); String _responseFromNativeCode = 'Waiting for Response...' ; Future< void > responseFromNativeCode() async { String response = "" ; try { final String result = await platform .invokeMethod( 'helloFromNativeCode' ); response = result; } on PlatformException catch (e) { response = "Failed to Invoke: ' ${e. message } '." ; } setState(() { _responseFromNativeCode = response; }); } @override Widget build(BuildContext context) { return Material( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment. spaceEvenly , children: [ RaisedButton( child: Text( 'Call Native Method' ), onPressed: responseFromNativeCode, ), Text( _responseFromNativeCode ), ], ), ), ); } }
结果
在Android和iOS设备上运行代码。 单击按钮“调用本机方法”
感谢 Atul Sharma 的文章。 如果您喜欢这篇文章,请随时单击该鼓掌按钮👏,以帮助其他人找到它。
本文是与移动技术相关的系列文章的一部分。 如果您正在寻找移动应用程序开发团队,请通过 info@47billion.com 与我们联系 。
最初于 2019 年1月15日 在 47billion.com 上 发布 。
From: https://hackernoon.com/creating-a-bridge-in-flutter-between-dart-and-native-code-b667f4dc164a