Flutter平台插件数据传递实现教程

Viewed 0

在之前写过的《Flutter进阶—平台插件》中,简单介绍了如何创建和使用Flutter插件,现在可以尝试编写一个能够在平台与客户端之间传递数据的Flutter平台插件。首先,需要了解平台插件的基本原理。

平台通道的结构概述如下:使用 MethodChannel 在客户端(UI)和主机(平台)之间传递消息,消息和响应异步传递以确保用户界面保持响应。在客户端,Flutter 的 MethodChannel 类可以发送与方法调用相对应的消息;在平台端,Android 上的 MethodChannel 类和 iOS 上的 FlutterMethodChannel 类可以接收方法调用并发送结果。这些类允许开发者开发平台插件,并且方法调用也可以反向发送,让平台作为客户端调用Dart方法。

标准平台通道使用标准消息编解码器,支持将JSON格式的值二进制序列化,包括布尔值、数字、字符串、字节缓冲区以及列表和映射等。发送和接收值时,会自动进行序列化和反序列化。下面表格展示了Dart值与平台端类型的映射关系:

Dart 类型 Android 类型 iOS 类型
null null nil (NSNull when nested)
bool java.lang.Boolean NSNumber numberWithBool:
int java.lang.Integer NSNumber numberWithInt:
int (32位不足) java.lang.Long NSNumber numberWithLong:
int (64位不足) java.math.BigInteger FlutterStandardBigInteger
double java.lang.Double NSNumber numberWithDouble:
String java.lang.String NSString
Uint8List byte[] FlutterStandardTypedData typedDataWithBytes:
Int32List int[] FlutterStandardTypedData typedDataWithInt32:
Int64List long[] FlutterStandardTypedData typedDataWithInt64:
Float64List double[] FlutterStandardTypedData typedDataWithFloat64:
List java.util.ArrayList NSArray
Map java.util.HashMap NSDictionary

了解原理后,可以通过IDE创建一个新的Flutter项目,例如名称为 share_to_wechat。默认项目模板使用Java编写Android代码、Objective-C编写iOS代码;如需使用Kotlin或Swift,可以使用 -i-a 标志,例如执行 flutter create -i swift -a kotlin share_to_wechat 命令。

Flutter部分

首先创建Flutter平台客户端,构建通道。使用 MethodChannel 并确保通道名称唯一,建议使用前缀如 samples.flutter.test/plugin

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class _MyHomePageState extends State<MyHomePage> {
  static const platform = const MethodChannel('samples.flutter.test/plugin');
  String _returnData = '';

  Future<Null> _dataInteraction() async {
    String returnData;
    try {
      final int result = await platform.invokeMethod('dataInteraction');
      returnData = '平台返回数据:$result';
    } on PlatformException catch (e) {
      returnData = '错误信息:${e.message}';
    }

    setState(() {
      _returnData = returnData;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Text('${_returnData}'),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _dataInteraction,
        tooltip: '获取平台数据',
        child: new Icon(Icons.autorenew),
      ),
    );
  }
}

Android部分

在Android平台实现中,打开Flutter项目的Android部分,在 MainActivity.java 中创建 MethodChannel 并设置 MethodCallHandler,使用相同的通道名称。

package com.yourcompany.testplugin;

import android.os.Bundle;
import java.util.Random;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
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;

public class MainActivity extends FlutterActivity {
  private static final String CHANNEL = "samples.flutter.test/plugin";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(new MethodCallHandler() {
      @Override
      public void onMethodCall(MethodCall call, Result result) {
        if (call.method.equals("dataInteraction")) {
          int data = getData();
          result.success(data);
        } else {
          result.notImplemented();
        }
      }
    });

    GeneratedPluginRegistrant.registerWith(this);
  }

  private int getData() {
    Random ran = new Random();
    return ran.nextInt(1000);
  }
}

iOS部分

在iOS平台实现中,打开Flutter项目的iOS部分,在 AppDelegate.m 中创建 FlutterMethodChannel 并设置方法调用处理程序。

#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import <Flutter/Flutter.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
  FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
                                          methodChannelWithName:@"samples.flutter.test/plugin"
                                          binaryMessenger:controller];
  [batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    if ([@"dataInteraction" isEqualToString:call.method]) {
      int data = [self getData];
      result(@(data));
    } else {
      result(FlutterMethodNotImplemented);
    }
  }];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (int)getData {
  int ran = arc4random() % 1000;
  return ran;
}

@end

完成上述步骤后,即可在Android和iOS平台上运行应用程序,通过点击按钮获取平台返回的随机数据。这个例子展示了Flutter平台插件的基本实现,通过修改 getData 方法可以实现特定的平台功能,例如官方教程中获取电池电量的示例。平台插件的开发相对简单,关键在于理解通道机制和数据类型映射。

0 Answers