Flutter和原生交互学习
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和原生交互学习的更多相关文章
- Flutter的需要与原生交互的一些常用库
[说明]由于这些库一直在更新,请自己选择合适的稳定版本下载. 另外如果发现有问题或者你有更好的库,欢迎留言告诉我. 谷歌官方的针对Dart语言的一些实用性的功能以及扩展的库 -- Quiver Qui ...
- h5 做app时和原生交互的小常识。
距离上次随笔或许有半年了吧,最近在用hybrid模式开发移动app,所以就简单的说说用h5技术开发app时候,做原生交互的几个小常识: 一.拨打电话或者发送短信: <a href="t ...
- Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信
背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 在 ...
- Lua和C++交互 学习记录之八:C++类注册为Lua模块
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之七:C++全局函数注册为Lua模块
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之六:全局函数交互
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之五:全局数组交互
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
- Lua和C++交互 学习记录之四:全局table交互
主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3 参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...
随机推荐
- springboot集成thymeleaf中遇到不能反悔页面,只能反悔字符串
错误:::::不能返回页面,只能返回字符串 原因::::在controller中使用了注解@RestController 修改注解为:@Controller 分析: RestController = ...
- destoon自定义函数获取地区名称
需要在api/extend.func.php 文件中加入的函数 获取地区名称 area_name($areaid) 传入地区id function area_name($areaid) { globa ...
- python_面向对象——动态创建类和isinstance和issubclass方法
# 给动态生产的类定义一个方法 def __init__(self,name): self.name = name print(self.name) def take(self,obj): print ...
- CF827D Best Edge Weight 题解
题意: 给定一个点数为 n,边数为 m,权值不超过 \(10^9\) 的带权连通图,没有自环与重边. 现在要求对于每一条边求出,这条边的边权最大为多少时,它还能出现在所有可能的最小生成树上,如果对于任 ...
- P3674 小清新人渣的本愿 莫队+bitset
ennmm...bitset能过系列. 莫队+bitset \(\mathcal{O}(m\sqrt n + \frac{nm}{w})\) 维护一个正向的 bitset <N> mem ...
- 洛谷 P816 忠诚 题解
每日一题 day28 打卡 Analysis 这道题用线段树维护区间最小值很简单,因为没有修改所以连lazy_tag都不用,但是这道题可以用树状数组维护区间最小值,非常骚气. 线段树代码: #incl ...
- 从0到N建立高性价比的大数据平台(转载)
2016-07-29 14:13:23 钱曙光 阅读数 794 原文链接:https://blog.csdn.net/qiansg123/article/details/80124521 声明:本文为 ...
- 解决VS2010自带的C/C++编译器CL找不到mspdb100.dll的问题
https://www.cnblogs.com/dudu/archive/2011/05/21/2053104.html 更好解决方法是在命令行中运行vsvars32.bat: "C:\Pr ...
- php+ tinymce粘贴word
最近公司做项目需要实现一个功能,在网页富文本编辑器中实现粘贴Word图文的功能. 我们在网站中使用的Web编辑器比较多,都是根据用户需求来选择的.目前还没有固定哪一个编辑器 有时候用的是UEditor ...
- 【JS】基础知识
引言 在互联网的演化过程中,网页制作是Web1.0时代的产物,那时网站的主要内容都是静态的,用户使用网站的行为也以浏览为主. 2005年以后,互联网进入了Web2.0时代,各类似桌面软件的Web应用大 ...