PlatformChannel功能简介

PlatformChannel分为BasicMessageChannel、MethodChannel以及EventChannel三种。其各自的主要用途如下:

  • BasicMessageChannel: 用于传递数据。Flutter与原生项目的资源是不共享的,可以通过BasicMessageChannel来获取Native项目的图标等资源。
  • MethodChannel: 传递方法调用。Flutter主动调用Native的方法,并获取相应的返回值。比如获取系统电量,发起Toast等调用系统API,可以通过这个来完成。
  • EventChannel: 传递事件。这里是Native将事件通知到Flutter。比如Flutter需要监听网络情况,这时候MethodChannel就无法胜任这个需求了。EventChannel可以将Flutter的一个监听交给Native,Native去做网络广播的监听,当收到广播后借助EventChannel调用Flutter注册的监听,完成对Flutter的事件通知。

其实可以看到,无论传方法还是传事件,其本质上都是数据的传递,不过上层包的一些逻辑不同而已。

flutter

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; class ChannelPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _ChannelPageState();
}
} class _ChannelPageState extends State<ChannelPage> { //获取到插件与原生的交互通道
static const jumpPlugin = const MethodChannel('com.example.jump/plugin');
static const counterPlugin = const EventChannel('com.example.counter/plugin');
var _count;
StreamSubscription _counterSub;
@override
void initState() {
super.initState();
_startCounterPlugin();
} @override
void dispose() {
super.dispose();
_endCounterPlugin();
}
void _startCounterPlugin(){
if(_counterSub == null){
_counterSub = counterPlugin.receiveBroadcastStream().listen(_onCounterEvent,onError: _onCounterError);
}
} void _endCounterPlugin(){
if(_counterSub != null){
_counterSub.cancel();
}
}
void _onCounterError(Object error) {
setState(() {
_count = "计时器异常";
print(error);
});
} void _onCounterEvent(Object event) {
setState(() {
_count = event;
});
} Future<Null> _jumpToNative() async {
String result = await jumpPlugin.invokeMethod('oneAct'); print(result);
} Future<Null> _jumpToNativeWithValue() async { Map<String, String> map = { "flutter": "这是一条来自flutter的参数" }; String result = await jumpPlugin.invokeMethod('twoAct', map); print(result);
} @override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Channel"),
centerTitle: true,
),
body: new Center(
child: new ListView(
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0),
child: new RaisedButton(
textColor: Colors.black,
child: new Text('跳转到原生界面'),
onPressed: () {
_jumpToNative();
}),
),
new Padding(
padding: const EdgeInsets.only(
left: 10.0, top: 10.0, right: 10.0),
child: new RaisedButton(
textColor: Colors.black,
child: new Text('跳转到原生界面(带参数)'),
onPressed: () {
_jumpToNativeWithValue();
}),
), new Padding(
padding: const EdgeInsets.only(
left: 10.0, top: 10.0, right: 10.0),
child: new Text('这是一个从原生发射过来的数据:$_count'),
), ],
)
),
);
}
}

android

package com.example.flutter_app.plugins;

import android.app.Activity;
import android.util.Log; import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.PluginRegistry; public class FlutterPluginCounter implements EventChannel.StreamHandler { public static String CHANNEL = "com.example.counter/plugin"; static EventChannel channel; private Activity activity; private FlutterPluginCounter(Activity activity) {
this.activity = activity;
} public static void registerWith(PluginRegistry.Registrar registrar) {
channel = new EventChannel(registrar.messenger(), CHANNEL);
FlutterPluginCounter instance = new FlutterPluginCounter(registrar.activity());
channel.setStreamHandler(instance);
// basicMessageChannel = new BasicMessageChannel<String> ("foo", StringCodec.INSTANCE);
} @Override
public void onListen(Object o, final EventChannel.EventSink eventSink) {
eventSink.success(123456);
} @Override
public void onCancel(Object o) {
Log.i("FlutterPluginCounter", "FlutterPluginCounter:onCancel");
} }
package com.example.flutter_app.plugins;

import android.app.Activity;
import android.content.Intent; import com.example.flutter_app.OneActivity;
import com.example.flutter_app.TwoActivity; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.PluginRegistry; public class FlutterPluginJumpToAct implements MethodCallHandler { public static String CHANNEL = "com.example.jump/plugin"; static MethodChannel channel; private Activity activity; private FlutterPluginJumpToAct(Activity activity) {
this.activity = activity;
} public static void registerWith(PluginRegistry.Registrar registrar) {
channel = new MethodChannel(registrar.messenger(), CHANNEL);
FlutterPluginJumpToAct instance = new FlutterPluginJumpToAct(registrar.activity());
//setMethodCallHandler在此通道上接收方法调用的回调
channel.setMethodCallHandler(instance);
} @Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) { //通过MethodCall可以获取参数和方法名,然后再寻找对应的平台业务,本案例做了2个跳转的业务 //接收来自flutter的指令oneAct
if (call.method.equals("oneAct")) { //跳转到指定Activity
Intent intent = new Intent(activity, OneActivity.class);
activity.startActivity(intent); //返回给flutter的参数
result.success("success");
}
//接收来自flutter的指令twoAct
else if (call.method.equals("twoAct")) { //解析参数
String text = call.argument("flutter"); //带参数跳转到指定Activity
Intent intent = new Intent(activity, TwoActivity.class);
intent.putExtra(TwoActivity.VALUE, text);
activity.startActivity(intent); //返回给flutter的参数
result.success("success");
}
else {
result.notImplemented();
}
} }
package com.example.flutter_app;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button; public class OneActivity extends Activity implements View.OnClickListener { private Button mGoFlutterBtn; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_one); mGoFlutterBtn = findViewById(R.id.go_flutter); mGoFlutterBtn.setOnClickListener(this); } @Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.go_flutter:
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
break;
}
} }
package com.example.flutter_app;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView; public class TwoActivity extends Activity{ private TextView mTextView; public static final String VALUE = "value"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_two); mTextView = findViewById(R.id.text); String text = getIntent().getStringExtra(VALUE); mTextView.setText(text); } }
package com.example.flutter_app;

import android.os.Bundle;

import com.example.flutter_app.plugins.FlutterPluginCounter;
import com.example.flutter_app.plugins.FlutterPluginJumpToAct; import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant; public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
FlutterPluginJumpToAct.registerWith(this.registrarFor(FlutterPluginJumpToAct.CHANNEL));//注册
FlutterPluginCounter.registerWith(this.registrarFor(FlutterPluginCounter.CHANNEL));//注册 }
}

效果:

Flutter和原生交互学习的更多相关文章

  1. Flutter的需要与原生交互的一些常用库

    [说明]由于这些库一直在更新,请自己选择合适的稳定版本下载. 另外如果发现有问题或者你有更好的库,欢迎留言告诉我. 谷歌官方的针对Dart语言的一些实用性的功能以及扩展的库 -- Quiver Qui ...

  2. h5 做app时和原生交互的小常识。

    距离上次随笔或许有半年了吧,最近在用hybrid模式开发移动app,所以就简单的说说用h5技术开发app时候,做原生交互的几个小常识: 一.拨打电话或者发送短信: <a href="t ...

  3. Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信

    背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...

  4. Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...

  5. Lua和C++交互 学习记录之八:C++类注册为Lua模块

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...

  6. Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...

  7. Lua和C++交互 学习记录之六:全局函数交互

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...

  8. Lua和C++交互 学习记录之五:全局数组交互

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...

  9. Lua和C++交互 学习记录之四:全局table交互

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...

随机推荐

  1. java加密算法-SHA1

    public class SHAUtil { /*** * SHA加密 生成40位SHA码 * @param 待加密字符串 * @return 返回40位SHA码 */ public static S ...

  2. 关于元素间的边距重叠问题与BFC

    一.边距重叠常见情况 1.垂直方向上相邻元素的重叠 (水平方向上不会发生重叠) 2. 垂直方向上父子元素间的重叠 二.BFC 1.什么是 BFC BFC(Block Formatting Contex ...

  3. 配置logback日志管理的时候

    在使用logback时候,需要引入 thymeleaf的配置 thymeleaf: suffix: .html check-template-location: true encoding: UTF- ...

  4. AHOI2013 差异 和 BZOJ3879 SvT

    差异 题目描述 给定一个长度为 $n$ 的字符串 $S$,令 $T_i$ 表示它从第 $i$ 个字符开始的后缀.求 $\displaystyle \sum_{1\leqslant i<j\leq ...

  5. 二.protobuf3数据类型

    定义数据类型 首先让我们看一个非常简单的例子.假设您想要定义搜索请求消息格式,其中每个搜索请求都有一个查询字符串.您感兴趣的特定结果页面以及每页的结果数量.这是用来定义消息类型的.proto文件. s ...

  6. Oracle-分析函数之取上下行数据lag()和lead()

    这两个函数是偏移量函数,可以查出一个字段的上一个值或者下一个值,配合over来使用. lead函数,这个函数是向上偏移. lag函数是向下偏移一位. 语法 [语法] lag(EXPR,<OFFS ...

  7. BZOJ 2502 清理雪道(有源汇上下界最小流)

    题面 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机, ...

  8. Linux 服务器用户间ssh免密码登录

    1.本脚本为服务器用户间密码互信登录脚本 2.依赖 需要安装expect工具 3.使用 sh CreateUserssh.sh hadoop hadoop /home/hadoop/.ssh 三个带入 ...

  9. (尚002)Vue的基本使用

    输入端在上面变化的同时,下面的内容也在变 View-->DOM监听-->指令;大括号数据 {{username}} Model-->模型(简单来说就是data,数据供view自动去读 ...

  10. java大文件分块上传断点续传demo

    第一点:Java代码实现文件上传 FormFile file = manform.getFile(); String newfileName = null; String newpathname =  ...