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. python高级特性-迭代器

    凡是可作用于for循环的对象都是Iterable类型: 凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列: 集合数据类型如list.dict.str等是Itera ...

  2. Java精通并发-notify方法详解及线程获取锁的方式分析

    wait(): 在上一次https://www.cnblogs.com/webor2006/p/11404521.html中对于无参数的wait()方法的javadoc进行了解读,而它是调用了一个参数 ...

  3. NET Framework 的泛型

    NET Framework 的泛型 泛型是具有占位符(类型参数)的类.结构.接口和方法,这些占位符是类.结构.接口和方法所存储或使用的一个或多个类型的占位符.泛型集合类可以将类型参数用作它所存储的对象 ...

  4. 开启idea自动Build功能

    修改Intellij IDEA的配置两步:1.setting -> Compile -> Build project automatically --> 选中 2.CTRL + SH ...

  5. 题解 UVa11388

    题目大意 \(T\) 组数据,每组数据给定两个整数 \(G,L\),输出数对 \(x,y\) 满足 \(GCD(x,y)=G,LCM(x,y)=L\) 且 \(x\) 最小.若无解则输出 \(-1\) ...

  6. SSM整合Dubbo登陆案例

    登陆案例 一.创建Service项目存放共同数据 1.1  创建实体类 private long id; private String loginName; private String userNa ...

  7. #6085. 「美团 CodeM 资格赛」优惠券

    题目描述 用last[x]表示对x进行的上一次操作的位置,vis[x]表示x是否在大楼内. Splay维护'?'的位置. 若x要进楼: 1.若x已在楼内,则去找last[x]到i之间是否有'?',若有 ...

  8. Codevs 1500 后缀排序(后缀数组)

    1500 后缀排序 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 天凯是MIT的新生.Prof. HandsomeG给了他一个 ...

  9. 【dp】P1026 统计单词个数

    题目描述 给出一个长度不超过200200的由小写英文字母组成的字母串(约定;该字串以每行2020个字母的方式输入,且保证每行一定为2020个).要求将此字母串分成kk份(1<k \le 401& ...

  10. shell编程题(三)

    将一目录下所有的文件的扩展名改为bak #! /bin/bash for i in `ls` do mv $i ${i%%.*}.bak done ${i%%.*} 截掉一个变量字符串第一个" ...