Flutter – Dart代码调用Kotlin原生代码
背景
开发中,我们常常需要调用原生Android的代码,因此我们需要通过一种方式来传递调用结果或者执行某个过程。在Flutter开发中,官方给我们提供了比较方便的方式来处理这种问题。MethodChannel, 顾名思义,方法渠道,也可以理解为一种通讯方式。
如何使用?
可能一些朋友对官方文档看得有点迷糊,这里我用我所理解并写出的案例帮助大家学习。举个栗子,开发中,我们使用最多的Toast消息框,但是Flutter并不提供Toast相关方法,那么我们就要自己造轮子把Toast从原生代码引入Dart代码中。
ToastProviderPlugin – 提供Toast相关的方法,提供Toast注册到Flutter中
object ToastProviderPlugin { /** Channel名称 **/ private const val ChannelName = "com.mrper.framework.plugins/toast" /** * 注册Toast插件 * @param context 上下文对象 * @param messenger 数据信息交流对象 */ @JvmStatic fun register(context: Context, messenger: BinaryMessenger) = MethodChannel(messenger, ChannelName).setMethodCallHandler { methodCall, result -> when (methodCall.method) { "showShortToast" -> showToast(context, methodCall.argument<String>("message"), Toast.LENGTH_SHORT) "showLongToast" -> showToast(context, methodCall.argument<String>("message"), Toast.LENGTH_LONG) "showToast" -> showToast(context, methodCall.argument<String>("message"), methodCall.argument<Int>("duration")) } result.success(null) //没有返回值,所以直接返回为null } private fun showToast(context: Context, message: String, duration: Int) = Toast.makeText(context, message, duration).show() }
MainActivity – 注册Toast插件,不然Flutter无法调用
class MainActivity() : FlutterActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) GeneratedPluginRegistrant.registerWith(this) ToastProviderPlugin.register(this, flutterView) //注册Toast插件 } }
main.dart – Dart语言中调用Toast插件, 重要类MethodChannel (源自’package:flutter/services.dart’)
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', theme: new ThemeData( primarySwatch: Colors.blue, ), home: new MyHomePage(title: 'Flutter Demo Home Page'), ); } } 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> { //声明一个调用对象,需要把kotlin中注册的ChannelName传入构造函数 static const _platform = const MethodChannel('com.mrper.framework.plugins/toast'); void _incrementCounter() { _platform.invokeMethod('showShortToast', { 'message': '你点击了按钮!'}); //调用相应方法,并传入相关参数。 } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text(widget.title), ), body: new Center( child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ new Text( 'You have pushed the button this many times:', ), new Text( 'fsfsfsdfsdf', style: Theme .of(context) .textTheme .display1, ), ], ), ), floatingActionButton: new FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: new Icon(Icons.add), ), ); } }
Toast可以在Dart语言中重新组装一下,以方便调用
import 'package:flutter/services.dart'; class Toast { static const _platform = const MethodChannel("com.mrper.framework.plugins/toast"); static void showShortToast(String message) => _platform.invokeMethod("showShortToast", { "message": message}); static void showLongToast(String message) => _platform.invokeMethod("showLongToast", { "message": message}); static void showToast(String message, int duration) => _platform.invokeMethod( "showToast", { "message": message, "duration": duration}); }
结论:使用Dart调用Kotin语言,重点是MethodCall,以及如何通过MethodCall获取相对应的方法名和方法参数。然后,Dart中根据原生定义的方法名及参数传入相对应的对象即可。