之前我们分享过flutter的app开发,不过那是单纯的flutter开发,实际使用中因为flutter通用与Android与IOS所以一般采用的应该是Android与flutter的混合的开发。

今天作此笔记,记录 Android 与 flutter 混合开发的 的记录,以及测试Android与flutter之间的通信方式。

目录

一、Android与flutter混合开发

二、Android 与 flutter 之间的消息通信

2.1、MethodChannel 方式传递信息(单向)

2.2 EventChannel 方式传递信息(单项)

2.3 BasicMeaageChannel 方式传递消息(双向的)


一、Android与flutter混合开发

首先我们在Android studio 中新建一个Android项目(此处使用的 kotlin)。

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第1张图片       flutter 与 android 混合开发 以及 Android与flutter之间的通信_第2张图片

Android 项目新建完成之后,我们新建一个flutter项目,new->new flutter project,选中 flutter module

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第3张图片       flutter 与 android 混合开发 以及 Android与flutter之间的通信_第4张图片

当flutter项目构建好了之后,我们在Android项目中以module导入flutter项目。new->new module,选中 import flutter module,点击next选则我们刚才新建的flutter module

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第5张图片         flutter 与 android 混合开发 以及 Android与flutter之间的通信_第6张图片

然后等待项目构建完成。

完成之后我们看以下项目中的一些变化 ,首先是 app下面的build.gradle增加了依赖

settings.gradle增加了setBinding

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第7张图片

在项目的目录中也有flutter的依赖,与Android的module相同。

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第8张图片

module已经导入了,接下来我们需要从Android中集成flutter的页面了。为了便于观察我们新建一个 FlutterActivity 来加载flutter部分,MainActivity 作为原生的界面跳转入口。

在MainActivity中添加两个按钮用来跳转,xml布局文件修改如下:

    

在MainActivity中为两个按钮添加点击跳转事件:

btn_jump_f1.setOnClickListener {    startActivity("pager" to 1)}btn_jump_f2.setOnClickListener {    startActivity("pager" to 2)}

FlutterActivity 的代码如下

class FlutterActivity :AppCompatActivity(){    @SuppressLint("SetTextI18n")    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_flutter)        //创建flutter view        val flutterView=Flutter.createView(this,lifecycle,"addflutter")        val params = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT , LinearLayout.LayoutParams.MATCH_PARENT )        linear_flutter.addView(flutterView,params)    }

注意:使用 startActivity("pager" to 2) 需要在build.gradle中添加依赖

implementation 'org.jetbrains.anko:anko:0.10.4'

还需要修改 build.gradle 中的 minSdkVersion 修改为 26否则运行程序的时候会报错

Error: Invoke-customs are only supported starting with Android O (--min-api 26)

运行之后的界面:

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第9张图片         flutter 与 android 混合开发 以及 Android与flutter之间的通信_第10张图片

上右图可以看到典型的flutter新项目的界面图:

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第11张图片

我们实现了flutter的页面的加载。在创建flutterview的时候我们给出了3个参数 activity , lifecycle name 。其中 name 是作为一个标识参数在传递到flutter页面之后,我们可以根据这个值来区分我们加载的页面。flutter端获取此值的代码为:window.defaultRouteName

首先我们在跳转到FlutterActivity页面时 携带的参数 pager 是不同的,可以根据这个值来区分flutter加载不同的页面,修改flutter端的代码:

void main() => runApp(MyApp(route: window.defaultRouteName,));class MyApp extends StatelessWidget {  // This widget is the root of your application.  String route;  MyApp({this.route});  @override  Widget build(BuildContext context) {    return MaterialApp(      title: "flutter_pager",      home: _getHomeByRoute(),    );  }  Widget _getHomeByRoute(){    switch(route){      case "pager1":        return PagerOne(title: route,);      default:        return PagerTwo(title: route,);    }  }}class PagerOne extends StatefulWidget {  PagerOne({Key key, this.title}) : super(key: key);  final String title;  @override  _PagerOneState createState() => _PagerOneState();}class _PagerOneState extends State {  int _counter = 0;  void _incrementCounter() {    setState(() {      _counter++;    });  }  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text("this is pager 1"),      ),      body: Center(        child: Column(          mainAxisAlignment: MainAxisAlignment.center,          children: [            Text(              'this is pager 1',            ),            Text(              '$_counter',              style: Theme.of(context).textTheme.display1,            ),          ],        ),      ),      floatingActionButton: FloatingActionButton(        onPressed: _incrementCounter,        tooltip: 'Increment',        child: Icon(Icons.add),      ), // This trailing comma makes auto-formatting nicer for build methods.    );  }}class PagerTwo extends StatefulWidget {  PagerTwo({Key key, this.title}) : super(key: key);  final String title;  @override  _PagerTwoState createState() => _PagerTwoState();}class _PagerTwoState extends State {  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text("pager 2"),      ),      body: Center(        child: Column(          mainAxisAlignment: MainAxisAlignment.center,          children: [            Text(              'this is pager 2',            ),          ],        ),      ),    );  }}

flutter端将根据 window.defaultRouteName 获取的字符串来决定加载 PagerOne 或者 PagerTwo.修改Android端FlutterActivity的代码为:

class FlutterActivity :AppCompatActivity(){    @SuppressLint("SetTextI18n")    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_flutter)        val index=intent.getIntExtra("pager",1);        tv_mark.text="${tv_mark.text} pager=$index"        val pager= if(index==1){             "pager1"        }else{             "pager2"        }        //创建flutter view        val flutterView=Flutter.createView(this,lifecycle,pager)        val params= LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)        linear_flutter.addView(flutterView,params)    }}

运行代码的示例:

页面没做美化看起来可能比较丑,不过我们现在只是为了实现根据参数加载不同页面的效果而已,功能已经实现了,接下来我们开始实现 Android与flutter的消息互发。

二、Android 与 flutter 之间的消息通信

2.1、MethodChannel 方式传递信息(单向)

此方式是 把 Android 作为接受方,flutter 作为发送方。首先我们需要在Android 端注册 MethodChannel

MethodChannel(flutterView,"accept_from_flutter")    .setMethodCallHandler { methodCall, result ->    Log.d("+++++++++++",methodCall.method)    tv_accept_from_flutter.text=methodCall.argument("android")}

在flutter端设置发送的方法:

class _PagerTwoState extends State {  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text("pager 2"),      ),      body: Center(        child: Column(          mainAxisAlignment: MainAxisAlignment.center,          children: [            Text(              'this is pager 2',            ),            RaisedButton(              child: Text("MethodChannel 给Android发送消息"),              onPressed: (){                _methodChannelSendMessageToAndroid();              },            ),          ],        ),      ),    );  }  //消息发送  void _methodChannelSendMessageToAndroid() async {    var result=await MethodChannel("accept_from_flutter").invokeMapMethod("option",{"android":"我是MethodChanner flutter给android发送的消息"});  }}

运行示例

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第12张图片

需要注意的地方是 Android端的 MethodChannel(flutterview,name)与flutter端MethodChannel(name),两个方法中的name必须相同,下面涉及到的其他消息发送方式也需要注意此项

2.2 EventChannel 方式传递信息(单项)

此方式是把Android 作为信息发送方,首先需要在Android 端设置EventChannel 的异步发送方法,并且需要把EventChannel.StreamHandler中的onListen方法中的 eventSink 参数传递到外界,因为我们需要使用 eventSink.success来发送消息。

class FlutterSendActivity :AppCompatActivity(){    var eventSink:EventChannel.EventSink?=null    @SuppressLint("SetTextI18n")    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_flutter_send)        //创建flutter view        val flutterView=Flutter.createView(this,lifecycle,"pager3")        val params= LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)        linear_flutter.addView(flutterView,params)         EventChannel(flutterView,"send_to_flutter")            .setStreamHandler(object:EventChannel.StreamHandler{                override fun onListen(p0: Any?, event: EventChannel.EventSink?) {                    eventSink=event                }                override fun onCancel(p0: Any?) {                    print("++++++++++++++++")                }            })        btn_send_to_flutter.setOnClickListener {            eventSink!!.success("这是Android发送给flutter的消息")        }    }}

在flutter 端我们需要设置同样的EventChannel 用来接受消息。接收信息的方法为EventChannel("send_to_flutter").receiveBroadcastStream().listen()来接受消息,此用法的返回值是StreamSubscription _stream ,此用法与Android 的广播类似,在使用结束的时候需要在 dispose() 方法中调用 _stream?.cancel();来释放StreamSubscription

class _PagerThreeState extends State {    String content="this is pager 3";  StreamSubscription _stream;    @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text("pager 3"),      ),      body: Center(        child: Column(          mainAxisAlignment: MainAxisAlignment.center,          children: [            Text("EventChannel 接收来自 Android的消息"),            Text( content, ),          ],        ),      ),    );  }    @override  void initState() {    // TODO: implement initState    super.initState();    //除了 _onData 后面的三个参数可不传    _stream = EventChannel("send_to_flutter").receiveBroadcastStream().listen(_onData,onError: _onError,onDone: _onDown,cancelOnError: true);  }  void _onData(Object object){    setState(() {      content=object.toString();    });  }  void _onError(Object object){  }  void _onDown(){  }  @override  void dispose() {    // TODO: implement dispose    super.dispose();    if(_stream!=null){      _stream?.cancel();    }  }}   

运行示例:

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第13张图片

需要注意的地方是 Android端的 EventChannel(flutterview,name)与flutter端EventChannel(name),两个方法中的name必须相同,下面涉及到的其他消息发送方式也需要注意此项

2.3 BasicMeaageChannel 方式传递消息(双向的)

Android端同样需要注册接收方法

class FlutterBasicMessageChannelActivity :AppCompatActivity(){    @SuppressLint("SetTextI18n")    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_flutter_basic)        //创建flutter view        val flutterView=Flutter.createView(this,lifecycle,"pager4")        val params= LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)        linear_flutter.addView(flutterView,params)        val basicChannel=BasicMessageChannel(flutterView,"basicChannel", StringCodec.INSTANCE)        //BasicMessageChannel 接受消息方法        basicChannel.setMessageHandler { string, reply ->            tv_info_from_flutter.text=string        }        btn_send_to_flutter.setOnClickListener {            //BasicMessageChannel 发送消息方法            basicChannel.send("我是BasicMessageChannel Android 发给 flutter的消息")        }    }}

flutter端同样需要注册

class PagerFour extends StatefulWidget {  PagerFour({Key key, this.title}) : super(key: key);  final String title;  @override  _PagerFourState createState() => _PagerFourState();}class _PagerFourState extends State {  String content="this is pager 4";  BasicMessageChannel _basicMessageChannel=BasicMessageChannel("basicChannel", StringCodec());  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text("pager 4"),      ),      body: Center(        child: Column(          mainAxisAlignment: MainAxisAlignment.center,          children: [            Text("BasicMessageChannel 接收来自 Android的消息"),            Text( content, ),            RaisedButton(              child: Text("BasicMessageChannel 给 Android发送消息"),              onPressed: (){                _sendMessageToAndroid();              },            )          ],        ),      ),    );  }  @override  void initState() {    // TODO: implement initState    super.initState();    //BasicMessageChannel的消息接受方法    _basicMessageChannel.setMessageHandler((str){      setState(() {        content=str;      });    });  }  //发送方法  void _sendMessageToAndroid(){    _basicMessageChannel.send("我是 BasicMessageChannel 给Android的发送消息");  }}

运行示例:

flutter 与 android 混合开发 以及 Android与flutter之间的通信_第14张图片

需要注意的地方是 Android端的 BasicMessageChannel(flutterview,name)与flutter端BasicMessageChannel(name),两个方法中的name必须相同.

现在Android与flutter的通信实现了,我们可以使用各种参数的传递来实现我们所需要功能了。

CSDN源码下载

示例程序百度网盘下载

链接:https://pan.baidu.com/s/1HYdJGPOexN-2RubpCdtN_g
提取码:0r2n

 

更多相关文章

  1. Android跨进程通信IPC之9——Binder之Framework层C++篇2
  2. Android跨进程通信IPC之9——Binder之Framework层C++篇1
  3. Android Studio导入第三方类库的方法
  4. Android消息循环
  5. android 的常标签和方法 android 初学者
  6. Android给TextView添加点击事件的实现方法
  7. 赢得争论的方法只有一个,那就是避免争论
  8. Android 高级进阶之深入剖析消息机制
  9. 详细介绍MvcPager分页控件使用的实例方法

随机推荐

  1. [Android遊戲] 森林跑跑熊:iOS移植的殺時
  2. Android应用程序目录结构分析
  3. android中使用线程(比如修改textview的tex
  4. Go support for Android
  5. Android,GridLayout布局(简易计算器)
  6. Android 线程池来管理线程
  7. Android 组件属性
  8. Android 基本的UI布局
  9. android-R.string
  10. android 架构体系