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沒有解析,下次再說。