62Flutter与Native通信(二)

Flutter与Native通信(二)

1.简介

Flutter与Native通信,四种方式,MethodChannel、EventChannel、BasicMessageChannel

2.差异比较

  • route:由于在初始化flutter页面时会传递一个字符串——route,因此我们就可以拿route来做文章,传递自己想要传递的数据。该种方式仅支持单向数据传递且数据类型只能为字符串,无返回值。
  • EventChannel:EventChannel仅支持数据单向传递,无返回值
  • MethodChannel:MethodChannel支持数据双向传递,有返回值。
  • BasicMessageChannel:BasicMessageChannel支持数据双向传递,有返回值。

3.MethodChannel使用

MethodChannel通信,是基于FlutterEngine来实现的,FlutterEngine作为中间连接桥路。 MethodChannel.

注意:在启动Flutter的Activity(FlutterActivity)中,通信测试好像没什么效果

62Flutter与Native通信(二)_第1张图片

消息和响应以异步的形式进行传递,以确保用户界面能够保持响应。

平台通道数据类型及编解码器

标准平台通道使用标准消息编解码器,它支持简单的类似 JSON 值的高效二进制序列化,例如布尔值、数字、字符串、字节缓冲区及这些类型的列表和映射(详情请参阅 StandardMessageCodec)。当你发送和接收值时,它会自动对这些值进行序列化和反序列化。

下表展示了如何在平台端接收 Dart 值,反之亦然:

Dart Java Kotlin OC Swift
null null null nil (NSNull when nested) nil
bool java.lang.Boolean Boolean NSNumber numberWithBool: NSNumber(value: Bool)
int java.lang.Integer Int NSNumber numberWithInt: NSNumber(value: Int32)
int, if 32 bits not enough java.lang.Long Long NSNumber numberWithLong: NSNumber(value: Int)
double java.lang.Double Double NSNumber numberWithDouble: NSNumber(value: Double)
String java.lang.String String NSString String
Uint8List byte[] ByteArray FlutterStandardTypedData typedDataWithBytes: FlutterStandardTypedData(bytes: Data)
Int32List int[] IntArray FlutterStandardTypedData typedDataWithInt32: FlutterStandardTypedData(int32: Data)
Int64List long[] LongArray FlutterStandardTypedData typedDataWithInt64: FlutterStandardTypedData(int64: Data)
Float64List double[] DoubleArray FlutterStandardTypedData typedDataWithFloat64: FlutterStandardTypedData(float64: Data)
List java.util.ArrayList List NSArray Array
Map java.util.HashMap HashMap NSDictionary Dictionary

1. Activity与Flutter通信

 private void setListener() {
     
        FlutterEngine flutterEngine = FlutterEngineCache.getInstance().get("my_engine_id");
        GeneratedPluginRegistrant.registerWith(flutterEngine); //Flutter2.0之后,可以去掉
        methodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL);
        methodChannel.setMethodCallHandler(
                (call, result) -> {
     
                    if (call.method.equals("getBatteryLevel")) {
     
                        int batteryLevel = getBatteryLevel();
                        if (batteryLevel != -1) {
     
                            result.success(batteryLevel);
                        } else {
     
                            result.error("UNAVAILABLE", "Battery level not available.", null);
                        }
                    } else {
     
                        result.notImplemented();
                    }
                }
        );
    }
    private int getBatteryLevel() {
     
        int batteryLevel;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
     
            BatteryManager batteryManager = (BatteryManager) getSystemService(Context.BATTERY_SERVICE);
            batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        } else {
     
            Intent intent = new ContextWrapper(getApplicationContext()).registerReceiver(null, new 			       IntentFilter(Intent.ACTION_BATTERY_CHANGED));
            batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        }
        return batteryLevel;
    }

Flutter页面

import 'dart:async';

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

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() {
    return _MyHomePageState();
  }
}

class _MyHomePageState extends State {
  static const platform = const MethodChannel('samples.flutter.dev/battery');

  // Get battery level.
  String _batteryLevel = 'Unknown battery level.';

  Future _getBatteryLevel() async {
    String batteryLevel;
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    setState(() {
      _batteryLevel = batteryLevel;
    });
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Material(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ElevatedButton(
              child: Text('Get Battery Level'),
              onPressed: _getBatteryLevel,
            ),
            Text(_batteryLevel),
          ],
        ),
      ),
    );
  }
}

2.Fragment与Flutter通信

代码一致

3.FlutterView

代码一致

4.EventChannel

内部核心还是MethodChannel,只不过封装了,EventChannel,只能是Native->channel

package com.uih.flutternative;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.EventChannel;

public class EventActivity extends AppCompatActivity {
    private static final String CHANNEL_NAME = "com.flutter.guide.EventChannel";
    private TextView textView;
    private EventChannel eventChannel;
    private EventChannel.EventSink eventSink;
    private FlutterView flutterView;
    private FlutterEngine flutterEngine;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event);
        textView = findViewById(R.id.textView);
        flutterView = findViewById(R.id.flutterView);
        initFlutterView();
        setListener();
        textView.setOnClickListener(v -> {
            eventSink.success("hello world"); //一定要在主线程
        });
    }

    public void initFlutterView() {
        flutterEngine = new FlutterEngine(this);
        flutterEngine.getDartExecutor().executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
        );
        flutterView.attachToFlutterEngine(flutterEngine);
        flutterEngine.getNavigationChannel().setInitialRoute("/");//设置需要启动的页面
    }

    private void setListener() {
        eventChannel = new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL_NAME);
        eventChannel.setStreamHandler(new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                Toast.makeText(EventActivity.this,"channel",Toast.LENGTH_LONG).show();
                eventSink = events;
            }

            @Override
            public void onCancel(Object arguments) {
                eventSink = null;
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        flutterEngine.getLifecycleChannel().appIsResumed();
    }

    @Override
    protected void onPause() {
        super.onPause();
        flutterEngine.getLifecycleChannel().appIsInactive();
    }

    @Override
    protected void onStop() {
        super.onStop();
        flutterEngine.getLifecycleChannel().appIsPaused();
    }
}

Flutter:

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

class EventChannelDemo extends StatefulWidget {
  @override
  _EventChannelDemoState createState() => _EventChannelDemoState();
}

class _EventChannelDemoState extends State {
  var _eventChannel = EventChannel('com.flutter.guide.EventChannel');
  var _data;

  @override
  void initState() {
    super.initState();
    _eventChannel
        .receiveBroadcastStream()
        .listen(_onData, onError: _onError, onDone: _onDone);
  }

  _onData(event) {
    setState(() {
      _data = event;
    });
  }

  _onError(event) {
    setState(() {
      _data = event;
    });
  }

  _onDone() {}

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Text('$_data'),
      ),
    );
  }
}

5.BasicMessageChannel

1.发送消息

BasicMessageChannel(String name, MessageCodec codec, {BinaryMessenger binaryMessenger})

注意:相对与其他Channel类型的创建,MessageChannel的创建除了channel名以外,还需要指定编码方式:

​ 发送的消息会以二进制的形式进行处理,所以要针对不同类型的数进行二进制编码

优点:类似于Android中Binder通信,适合相对大的数据传输,而且还能回复

编码类型 消息格式
BinaryCodec 发送二进制消息时
JSONMessageCodec 发送Json格式消息时
StandardMessageCodec 发送基本型数据时
StringCodec 发送String类型消息时
package com.uih.flutternative;


import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.StringCodec;

public class BasicActivity extends FlutterActivity {
     
    private TextView textView;
    private FlutterView flutterView;
    private FlutterEngine flutterEngine;
    private BasicMessageChannel basicMessageChannel;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
     
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_basic);
        textView = findViewById(R.id.textView);
        flutterView = findViewById(R.id.flutterView);
        initFlutterView();
        setListener();
    }
    public void initFlutterView() {
     
        flutterEngine = new FlutterEngine(this);
        flutterEngine.getDartExecutor().executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
        );
        flutterView.attachToFlutterEngine(flutterEngine);
        flutterEngine.getNavigationChannel().setInitialRoute("/");//设置需要启动的页面
    }

    private void setListener() {
     
        basicMessageChannel = new BasicMessageChannel(
                flutterEngine.getDartExecutor().getBinaryMessenger(),
                "com.example.messagechannel/interop",
                StringCodec.INSTANCE);
        //监听接收消息
        basicMessageChannel.setMessageHandler((message, reply) -> {
     
            Toast.makeText(BasicActivity.this, "Received message =" + message, Toast.LENGTH_LONG).show();
            reply.reply("Reply from Android"); //回复值
        });

        textView.setOnClickListener(v -> {
     
            basicMessageChannel.send("Hello World from Android", reply -> {
     
                Toast.makeText(BasicActivity.this, "" + reply, Toast.LENGTH_LONG).show();
            });//发送, replay为回复值
        });
    }


    @Override
    protected void onResume() {
     
        super.onResume();
        flutterEngine.getLifecycleChannel().appIsResumed();
    }

    @Override
    protected void onPause() {
     
        super.onPause();
        flutterEngine.getLifecycleChannel().appIsInactive();
    }

    @Override
    protected void onStop() {
     
        super.onStop();
        flutterEngine.getLifecycleChannel().appIsPaused();
    }
}

Flutter

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

class BasicMessagerChannelDemo extends StatefulWidget {
  BasicMessagerChannelDemo({Key key}) : super(key: key);

  @override
  _BasicMessagerChannelDemoState createState() {
    return _BasicMessagerChannelDemoState();
  }
}

class _BasicMessagerChannelDemoState extends State {
  static const _channel = BasicMessageChannel('com.example.messagechannel/interop', StringCodec());
  String _platformMessage;

  void _sendMessage() async {
    final String reply = await _channel.send('Hello World form Dart');
    print(reply);//回复值
  }

  @override
  void initState() {
    super.initState();
    // Receive messages from platform
    _channel.setMessageHandler((String message) async { //监听
      print('Received message = $message');
      setState(() => _platformMessage = message);
      return 'Reply from Dart';
    });
    _sendMessage();
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Text('$_platformMessage'),
      ),
    );
  }
}

你可能感兴趣的:(Flutter,flutter)