MST

星途 面试题库

面试题:Flutter框架层与引擎层数据交互方式

在Flutter架构中,框架层和引擎层是如何进行数据交互的?请举例说明常用的数据传递场景及实现方式。
34.7万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

框架层和引擎层的数据交互方式

在Flutter架构中,框架层和引擎层通过消息通道(Message Channel)进行数据交互。框架层使用Dart代码,而引擎层主要由C++实现。消息通道允许Dart代码和C++代码相互调用,实现数据的传递和功能的交互。

常用数据传递场景及实现方式

  1. 平台调用(Platform Call):框架层调用引擎层提供的平台功能。
    • 场景:例如获取设备电量信息,这是依赖于原生系统的功能,需要通过引擎层来实现。
    • 实现方式
      • Dart端:使用MethodChannel类。首先创建一个MethodChannel实例,指定通道名称。然后调用invokeMethod方法来调用引擎层暴露的方法,并传递参数。例如:
import 'package:flutter/services.dart';

class Battery {
  static const MethodChannel _channel =
      const MethodChannel('samples.flutter.dev/battery');

  static Future<int> getBatteryLevel() async {
    try {
      final int result = await _channel.invokeMethod('getBatteryLevel');
      return result;
    } on PlatformException catch (e) {
      print("Failed to get battery level: '${e.message}'");
      return -1;
    }
  }
}
    - **C++端(引擎层)**:在C++中注册与Dart端通道名称一致的方法,并实现具体逻辑。在Flutter引擎中,通过`flutter::MethodChannel`来处理这些调用。例如:
#include "flutter/method_channel.h"
#include "flutter/plugin_registrar.h"
#include "flutter/standard_method_codec.h"

#include <jni.h>
#include <memory>

namespace battery {

class BatteryPlugin : public flutter::Plugin {
 public:
  static void RegisterWithRegistrar(flutter::PluginRegistrar* registrar) {
    auto channel =
        std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
            registrar->messenger(), "samples.flutter.dev/battery",
            &flutter::StandardMethodCodec::GetInstance());

    auto plugin = std::make_unique<BatteryPlugin>();

    channel->SetMethodCallHandler(
        [plugin_pointer = plugin.get()](const auto& call, auto result) {
          plugin_pointer->HandleMethodCall(call, std::move(result));
        });

    registrar->AddPlugin(std::move(plugin));
  }

  void HandleMethodCall(const flutter::MethodCall<flutter::EncodableValue>& call,
                        std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
    if (call.method_name().compare("getBatteryLevel") == 0) {
      // 这里获取实际的电量信息,示例中简单返回一个固定值
      int batteryLevel = 80; 
      result->Success(flutter::EncodableValue(batteryLevel));
    } else {
      result->NotImplemented();
    }
  }
};

}  // namespace battery

void RegisterBatteryPlugin(flutter::PluginRegistrar* registrar) {
  battery::BatteryPlugin::RegisterWithRegistrar(registrar);
}
  1. 事件流(Event Stream):引擎层向框架层推送实时数据。
    • 场景:如传感器数据(加速度计、陀螺仪等)实时更新,引擎层获取到数据后需要及时传递给框架层。
    • 实现方式
      • Dart端:使用EventChannel类。创建EventChannel实例并监听事件。例如监听设备方向变化事件:
import 'package:flutter/services.dart';

class OrientationStream {
  static const EventChannel _channel =
      const EventChannel('samples.flutter.dev/orientation');

  static Stream<dynamic> get orientationStream {
    return _channel.receiveBroadcastStream();
  }
}

然后在需要的地方订阅这个流:

OrientationStream.orientationStream.listen((event) {
  print('Device orientation changed: $event');
});
    - **C++端(引擎层)**:在C++中创建与Dart端对应的`EventChannel`,并在数据更新时发送事件。例如:
#include "flutter/event_channel.h"
#include "flutter/plugin_registrar.h"
#include "flutter/standard_method_codec.h"

#include <jni.h>
#include <memory>

namespace orientation {

class OrientationPlugin : public flutter::Plugin {
 public:
  static void RegisterWithRegistrar(flutter::PluginRegistrar* registrar) {
    auto channel =
        std::make_unique<flutter::EventChannel<flutter::EncodableValue>>(
            registrar->messenger(), "samples.flutter.dev/orientation",
            &flutter::StandardMethodCodec::GetInstance());

    auto plugin = std::make_unique<OrientationPlugin>();

    channel->SetStreamHandler(plugin.get());

    registrar->AddPlugin(std::move(plugin));
  }

  virtual ~OrientationPlugin() = default;

  flutter::EventSink event_sink_;

  flutter::PluginRegistrar* registrar_;

  // 模拟数据更新,这里简单发送一个固定值
  void SendOrientationUpdate() {
    if (event_sink_) {
      event_sink_(flutter::EncodableValue("landscape"));
    }
  }

  // 处理流的订阅和取消订阅
  flutter::ErrorOr<flutter::EventSink> OnListenInternal(
      const flutter::EncodableValue* arguments,
      std::unique_ptr<flutter::EventSink> events) override {
    event_sink_ = std::move(*events);
    // 这里可以开始监听实际的传感器数据更新,并调用SendOrientationUpdate方法发送数据
    return event_sink_;
  }

  flutter::ErrorOr<void> OnCancelInternal(
      const flutter::EncodableValue* arguments) override {
    event_sink_ = nullptr;
    return {};
  }
};

}  // namespace orientation

void RegisterOrientationPlugin(flutter::PluginRegistrar* registrar) {
  orientation::OrientationPlugin::RegisterWithRegistrar(registrar);
}