android 与 flutter 之间的通信

文章目录

  • 前言
  • 集成 flutter 混合开发
  • android 与 flutter 之间的通信
  • 总结
一、前言

因为flutter 具有跨平台的属性,既可以在android上跑,也能在ios 上跑,所以为了节约开发的成本,减少人力,势必就会用到它。然而已有的项目部不太可能重新写,所以就需要进行混合开发。也就是在原生中集成flutter,进行混合开发。混合开发就会遇到原生和flutter的通信问题,今个就讲讲原生和flutter的通信。

二、首先创建个flutter module,然后集成到app中

1、在原生项目的父目录下,使用命令,创建flutter项目:
flutter create -t module --org com.example flutter_demo
在这里插入图片描述
创建完毕,然后我们用as打开这个父目录,可以看到我们的flutter_demo 已经创建好了,如图:
在这里插入图片描述
2、在原生app里面的settings.gradle,include ‘:app’ 下面添加:

setBinding(new Binding([gradle: this]))
evaluate(new File(
    settingsDir.parentFile,
    'flutter_demo/.android/include_flutter.groovy'
))
include ':flutter_demo'

3、在原生app下的build.gradle中添加依赖:

dependencies {
	//...
	implementation project(':flutter')
}

添加完毕,我们切回 app的项目,运行会发现报错了。
在这里插入图片描述
报错是说flutterPlugin 没法用,这里在settings.gradle 将repositoriesMode改为:RepositoriesMode.PREFER_PROJECT。重新运行。
如果还遇到第三方解析失败,添加maven:

dependencyResolutionManagement {
  repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
  repositories {
    maven { url 'https://jitpack.io' }
    maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
    maven { url 'https://maven.aliyun.com/repository/central' }
    maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
    google()
    mavenCentral()
  }
}

另外在项目的build.gradel 添加:

allprojects {
  repositories {
    maven { url 'https://jitpack.io' }
    maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
    maven { url 'https://maven.aliyun.com/repository/central' }
    maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
    google()
    mavenCentral()
  }
}

然后运行app,就可以了。如果你还有其他报错,切换到根目录,去检查下flutter_demo里头的这两个文件。打开main.dart,提示你Enable Dart support,点击它就可以。然后再打开 pubspec.yaml ,点击pub get 获取相应的依赖。确保flutter项目的环境和依赖库没问题。

到这里,我们的flutter_demo 就集成到我们的app中了。接下来就是看android和flutter的通信

三、android和flutter的通信

上面的项目,每次要看flutter代码是不是每次都要切过来切过去的,所以呢,我们可以在setting.gradle 加上这么一行代码:
project(‘:flutter_demo’).projectDir = new File(‘…/flutter_demo’)
在这里插入图片描述
这样,我们在app的项目中就能查看flutter的代码了。好了,我们最想知道的就是android 怎么打开 flutter页面。接这往下看。

1、android 跳转 flutter:
在清单AndroidManifest里面添加 FlutterActivity

    <activity android:name="io.flutter.embedding.android.FlutterActivity"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize"
        >
    </activity>

点击跳转:

   binding.fab.setOnClickListener { view ->
      //跳转flutter
      startActivity(
        FlutterActivity.createDefaultIntent(this)
      )
    }

你会发现跳转很慢,所以,我们用带有缓存引擎的初始路由来启动FlutterActivity
创建一个MyApplication 然后 在onCreate 中进行缓存引擎的初始化。

    // 创建一个Flutter引擎
    flutterEngine = new FlutterEngine(this);

    // 开始执行 Dart 代码来预热flutter引擎
    flutterEngine.getDartExecutor().executeDartEntrypoint(
      DartExecutor.DartEntrypoint.createDefault()
    );

    //缓存Flutter引擎用来开启FlutterActivity
    FlutterEngineCache
      .getInstance()
      .put("my_engine_id", flutterEngine);
  }

这个我们就能使用缓存引擎跳转Flutter。

 binding.fab.setOnClickListener { view ->
      //跳转flutter
      startActivity(
        FlutterActivity
          .withCachedEngine("my_engine_id")
          .build(this)
      );
    }

很明显立马就跳转过去了。

2、如何跳转不同的flutter页面?
在applation 的onCreate 初始化需要跳转的页面, 到我们的Application 中的onCreate添加:

flutterEngine.getNavigationChannel().setInitialRoute("/test2");

然后修改main.dart 的代码:

void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
switch (route) {
 case '/test1':
   return const Test1();
 case '/test2':
   return const Test2();
 case '/test3':
   return const Test3();
 default:
   return const Test1();
}
}

Test1是Test1.dart,代表不同的页面。当我们要跳转不同的页面,只要修改
flutterEngine.getNavigationChannel().setInitialRoute(“/test2”);就可以了,比如我们要跳转到Test3页面改成 flutterEngine.getNavigationChannel().setInitialRoute(“/test3”);
这个很简单,根据不同的标识,跳转对应的页面就行了。

四、接下来,就是文章的主题,讲通信方式都有哪些?

BasicMsgChannel
MethodChannel
EventChannel

1、BasicMsgChannel 方式
双向的,原生可以给flutter发送,然后flutter同时也可以返回信息给原生

发送:

    val flutterEngine = MyApplication.flutterEngine
    val basicMessageChannel = BasicMessageChannel(
      flutterEngine.dartExecutor.binaryMessenger,
      "basicMessageChannel",
      StringCodec.INSTANCE
    )
    basicMessageChannel.send("通过basicMessageChannel发送消息"){
        message: String?->
      Log.d("ssz", "接收:$message") //message 是flutter发回给原生的消息
    }

flutter 接收:

_basicMessageChannel = const BasicMessageChannel('basicMessageChannel', StringCodec());
    _basicMessageChannel.setMessageHandler((String? message) => Future<String>((){
      setState(() {//刷新控件
        _basicMessage = "flutter接收了消息:${message!}";
      });
      return "flutter 收到了";//这里是返回信息给原生
    }));

我们也可以反过来,原生接收,flutter发送,如下:
原生接收:

    basicMessageChannel.setMessageHandler { message, reply ->
      Log.d("ssz", "接收:$message")
    }

flutter 发送:

      _basicMessageChannel.send("我是flutter的消息");

2、MethodChannel 方法
主要是flutter 调用原生

原生接收:

val methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "test2")
    binding.btnTest2.setOnClickListener {
      toFlutter()
      methodChannel.setMethodCallHandler { call, result ->
        if (call.method.equals("open")){
          Log.d("ssz", "接收flutter调用")
        }
      }
    }

flutter 发送

 const _methodChannel = MethodChannel('test2');
    _methodChannel.invokeListMethod("open");

3、EventChannel方法
主要是原生发送给flutter,这个方法使用不当就会接受不到,谨慎使用。

原生发送:

 val eventChannel = EventChannel(MyApplication.flutterEngine.dartExecutor.binaryMessenger, "test3")
    binding.btnTest3.setOnClickListener {
      toFlutter()
      eventChannel.setStreamHandler(object : StreamHandler{
        override fun onListen(arguments: Any?, events: EventSink?) {
          Log.d("ssz","执行了 onListen");
          events?.success("原生发送")
        }
        override fun onCancel(arguments: Any?) {
        }
      })

    }
  }

flutter 接收

void initState() {
    super.initState();
    Future.delayed(const Duration(milliseconds: 6000), () {//需要做个延迟,不然原生onListen会不执行,导致不能发送消息
      var eventChannel = const EventChannel("test3");
      eventChannel.receiveBroadcastStream().listen((dynamic event) {
        setState(() {
          _EventMessage = "flutter接收$event";
        });
      }, onError: (dynamic error){
        setState(() {
          _EventMessage = "flutter接收$error";
        });
      },cancelOnError: true);
    });

  }

最后呢,关于路由方面,有的业务可能需要跳转很多不同的页面,原生的方式不太友好,可以选择闲鱼开源的库 https://github.com/alibaba/flutter_boost ,提高开发的效率。

以上代码地址:https://github.com/shenshizhong/HybridFlutter

总结

总的来讲:
1、android集成flutter,进行混合开发
2、android 与 flutter 的通信
3、使用第三方提高开发效率

如果对你有一点点帮助,那是值得高兴的事情。:)
我的csdn:http://blog.csdn.net/shenshizhong
我的简书:http://www.jianshu.com/u/345daf0211ad

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值