Flutter MethodChannel 學習

one_cup發表於2018-06-07

Flutter MethodChannel 學習

好久沒寫東西,正好最近有時間又開始研究起來Flutter,不瞭解的童鞋可以去查查資料瞭解一下, 在我看來是目前我瞭解盜的最理想的跨平臺解決方案了。而跨平臺中一個比較重要的點就是與底層進行互動,本文就主要說一下在Flutter中是如何與Android進行通訊的(iOS應該同理)。不涉及到原始碼,只是簡單的使用和在使用過程中的一些想法。

建立初始的Demo

使用 flutter create methodchannellearn 建立一個 flutter 專案。

匯入 servicesasync
import 'dart:async'; import 'package:flutter/services.dart';

首先先在main.dart_MyHomePageState 中建立一個靜態成員變數methodChannel
static const MethodChannel methodChannel=const MethodChannel("flutter_method_channel");

然後修改原有的_incrementCounter()方法,內部呼叫methodChannel.invokeMethod()方法,呼叫Native端的方法。

void _incrementCounter() {
//    setState(() {
//      // This call to setState tells the Flutter framework that something has
//      // changed in this State, which causes it to rerun the build method below
//      // so that the display can reflect the updated values. If we changed
//      // _counter without calling setState(), then the build method would not be
//      // called again, and so nothing would appear to happen.
//      _counter++;
//    });
     methodChannel.invokeMethod("_incrementCounter", _counter++);
  }
複製程式碼

接下來就是在Android端新增響應的程式碼

@Override protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  GeneratedPluginRegistrant.registerWith(this);
  new MethodChannel(getFlutterView(), "flutter_method_channel").setMethodCallHandler(
      new MethodChannel.MethodCallHandler() {
        @Override public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
          if (methodCall.method.equals("_incrementCounter")) {
            toast(methodCall.arguments);
          }
        }
      });
}
複製程式碼

跑一下之後可以看到正常的toast彈出。

新增回撥

onMethodCall中我們可以看到還有另外的一個引數result,可以使用它將資料傳遞迴Flutter中。

修改Android端程式碼

if (methodCall.method.equals("_incrementCounter")) {
        if(methodCall.arguments instanceof Integer){
                int count= (int) methodCall.arguments;
                count++;
                result.success(count);
        }
    }
複製程式碼

同時修改Flutter中的程式碼

Future<Null> _incrementCounter() async {
//    setState(() {
//      // This call to setState tells the Flutter framework that something has
//      // changed in this State, which causes it to rerun the build method below
//      // so that the display can reflect the updated values. If we changed
//      // _counter without calling setState(), then the build method would not be
//      // called again, and so nothing would appear to happen.
//      _counter++;
//    });
    var result =
        await methodChannel.invokeMethod("_incrementCounter", _counter);
    setState(() {
      _counter = result;
    });
  }
複製程式碼

執行一下,點選次數正常增加。

主動通知Flutter

有時候我們可能會需要主動的通知flutter ,而不是等待flutter呼叫,利用回撥傳遞資料,這是就需要一個新的Channel, EventChannel

同樣還是剛才的例子,這會先修改flutter程式碼,使用EventChannel

static const EventChannel eventChannel =
      const EventChannel("flutter_event_channel");
  void _onData(event) {
    setState(() {
      _counter = event;
    });
  }
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    eventChannel.receiveBroadcastStream().listen(_onData);
  }
複製程式碼

然後修改Android的程式碼

new MethodChannel(getFlutterView(), "flutter_method_channel").setMethodCallHandler(
      new MethodChannel.MethodCallHandler() {
        @Override public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
          if (methodCall.method.equals("_incrementCounter")) {
            if (methodCall.arguments instanceof Integer) {
              int count = (int) methodCall.arguments;
              count++;
              if (eventSink != null) {
                eventSink.success(count);
              }
            }
          }
        }
      });
  new EventChannel(getFlutterView(), "flutter_event_channel").setStreamHandler(
      new EventChannel.StreamHandler() {
        @Override public void onListen(Object o, EventChannel.EventSink eventSink) {
          MainActivity.this.eventSink = eventSink;
        }
        @Override public void onCancel(Object o) {
          MainActivity.this.eventSink = null;
        }
      });
複製程式碼

同樣 執行,資料也能夠正常顯示

這裡EventChannel的使用場景應該會有好多,畢竟一個持久長時間的訊息通道在實際場景中會有很多應用。

專案的程式碼地址在這裡

相關文章