Dart4Flutter – 拾遗01 – flutter-dart环境搭建
Flutter 实例 – 从本地到Flutter通信 – Event Channels
Flutter 作为一种跨平台的解决方案,有访问本地资源的能力。主要是通过Channel完成,你可以称之为隧道。主要是MethodChannel和MessageChannel两种,第一种是调用方法,第二种是传递信息。首先通信的双方是Flutter和本地操作系统或者应用,而且方法的调用和消息的方法可以从任何一方发起,类似RPC(远程过程调用)。
重点内容:
- 主要是Flutter是一个比较独立的环境,要想访问本地的资源,Flutter提供了Channel机制,类似Cilent-Server模式或者RPC
- 通过Channel的名称打通Channel,隧道。
- Flutter和本地是对称的,请求可以从任何一发发起,本教程主要是从Flutter给本地发送请求。
Flutter部分
如果你对Flutter的界面编写部分不熟悉,可以参考官方的文档;
下面是UI部分的代码
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new Scaffold(
body: new PlatformTestBody(),
),
));
}
class PlatformTestBody extends StatefulWidget {
@override
PlatformTestBodyState createState() {
return new PlatformTestBodyState();
}
}
class PlatformTestBodyState extends State<PlatformTestBody> {
String nativeMessage ='';
@override
Widget build(BuildContext context) {
return new Container(
color: Colors.pinkAccent,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(left: 18.0, top: 200.0),
child: new Text(
'Tap the button to change your life!',
style: new TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 23.0),
),
),
new Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 102.0),
child: new RaisedButton(
child: new Text('Click Me'),
onPressed: () => print(''),
),
),
new Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 102.0),
child: new Text(
nativeMessage,
style: new TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 23.0),
),
)
],
),
);
}
}
复制代码
现在我们介绍关于本地资源访问的问题,首先我们要引入service包和async包。
// Add these lines to the top of the file
import 'package:flutter/services.dart';
import 'dart:async';
复制代码
有了service包,我们就可以配置Flutter,发送请求到本地。声明一个static const
变量platformMethodChannel
,赋值MethodChannel类型的对象。
class PlatformTestBodyState extends State<PlatformTestBody> {
//Add this line
static const platformMethodChannel = const MethodChannel('com.test/test');
String nativeMessage ='';
@override
Widget build(BuildContext context) {
...
复制代码
注意,我们给MethodChannel一个名字com.test/test
,这个名字和本地那边的要一样。
我们创建了MethodChannel,我们准备一个用来发送请求的函数。我们创建一个叫doNativeSuff
的异步函数
Future<Null> doNativeSuff() async {
}
复制代码
代替RaisedButton中的onPressed
函数 print('')
为doNativeSuff()
child: new RaisedButton(
child: new Text('Click Me'),
onPressed: () => print(''),
),
复制代码
child: new RaisedButton(
child: new Text('Click Me'),
onPressed: () => doNativeSuff(),
),
复制代码
下面解释整个doNativeSuff
方法
Future<Null> doNativeSuff() async {
String _message; // 1
try {
final String result =
await platformMethodChannel.invokeMethod('changeLife');// 2
_message = result;
print(result);
} on PlatformException catch (e) {
_message = "Sadly I can not change your life: ${e.message}.";
}
setState(() {
nativeMessage = _message; // 3
});
}
复制代码
- 声明一个String变量_message,用于存需要显示在界面上的信息,可能来自本地,也可能来自Flutter
- 发送请求,
await platformMethodChannel.invokeMethod('changeLife')
是调用本地的changeLife
方法,并且这个方法是异步的,await表示阻塞执行。 nativeMessage = _message;
表示通知Flutter状态改变,刷新界面。
本地部分
本教程只关注Android方面的代码。在Android studio 中打开MainActivity.java
,在文件的最顶上添加一下代码,是Flutter插件的相关依赖
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
复制代码
声明CHANNEL
变量,和Flutter中MethodChannel的名字一样com.test/test
,建议直接从Flutter那边复制粘贴。
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.test/test";
@Override
protected void onCreate(Bundle savedInstanceState) {
...
复制代码
使用上面的CHANNEL
和 FlutterView
创建一个MethodChannel
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.test/test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), CHANNEL)// 重点
复制代码
在MethodChannel的中调用.setMethodCallHandler()
方法,需要一个MethodCallHandler
对象,是一个匿名内部类,有一个方法onMethodCall
,在Flutter发送请求事,onMethodCall
方法会执行。
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.test/test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, Result result) {
}
}
);
}
}
复制代码
onMethodCall方法中有两个参数 MethodCall 和 result,MethodCall 中有关当前请求的信息,例如调用方法的名字changeLife
;Result用于发送信息给Flutter。
在onMethodCall中判断当前请求是否为changeLife
,如果是通过result
的 success
返回信息:Life Changed
.
public void onMethodCall(MethodCall methodCall, Result result) {
if (methodCall.method.equals("changeLife")){
String message ="Life Changed";
result.success(message);
}
...
复制代码
这样Flutter就可以访问,本地的方法了。
通常应用于访问本地资源,例如访问相机,本地存储,图片的选择
本教程主要了解的是MethodChannel,还有MessageChannel没有解析,下次再说。