本文主要内容是

一、flutter 与原生交互

       主要记录,如何原生数据传递给flutter ,flutter数据传给原生app。

二、flutter路由跳转

       flutter 页面跳转

一、flutter 与原生交互

第一步、Android studio 创建app ,项目名为TestFlutterEngine

创建flutter_moduel,在TestFlutterEngine文件上选择file->new flutter project,名称为test_engine_flutter_module

保持 TestFlutterEngine 与 test_engine_flutter_module在同一级目录

setting引入

//设置下面数据  TestFlutterEngine对应app名称   test_engine_flutter_module对应flutter module名称
setBinding(new Binding([gradle: this, mainModuleName: 'TestFlutterEngine']))
evaluate(new File(
        settingsDir.parentFile,
        'test_engine_flutter_module/.android/include_flutter.groovy'
))

build.gradle 引入flutter

implementation project(path: ':flutter')

现在,app与flutter进行关联了

第二步、想要app直接展示flutter 视图,需要初始化Engine 引擎,再绑定

FlutterFragment到activity布局里面
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initFlutterEngine()
        //初始化flutter 页面
        initFlutterFragment()
    }

    /**
     * 初始化 Flutter Engine引擎
     * Flutter Engine: 这是一个纯 C++实现的 SDK,其中囊括了 Skia引擎、Dart运行时、文字排版引擎等。
     */
    private fun initFlutterEngine() {
        mFlutterEngine = FlutterEngineCache.getInstance().get(engineId)
        if (null == mFlutterEngine) {
            mFlutterEngine = FlutterEngine(this)
            mFlutterEngine!!.navigationChannel.setInitialRoute("/")
            mFlutterEngine!!.dartExecutor.executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
            )
            FlutterEngineCache
                .getInstance()
                .put(engineId, mFlutterEngine)
        }
        initMethodChannel()
    }

    /**
     * 与flutter页面关联
     */
    private fun initFlutterFragment() {
        flutterFragment =
            FlutterFragment.withCachedEngine(engineId)
                .shouldAttachEngineToActivity(true)
                .build() as FlutterFragment

        supportFragmentManager
            .beginTransaction()
            .add(
                R.id.fragment_container,
                flutterFragment as Fragment,
                "flutter_fragment"
            ).commit()
    }
其中  R.id.fragment_container 对应的是xml中FragmentLayout控件

然后对Engine引擎的释放

override fun onDestroy() {
        super.onDestroy()
        releaseFlutterEngine()
    }


    /**
     * 释放flutter引擎
     */
    private fun releaseFlutterEngine() {
        mFlutterEngine?.let { engine ->
            FlutterEngineCache.getInstance().remove(engineId)
            engine.destroy()
        }
        mFlutterEngine = null
    }

第三步,建立通道,实现原生与flutter交互

/**
     *  初始化channel 通道
     *  可以有多个 通道
     */
    private fun initMethodChannel(){
        mMethodChannel = MethodChannel(mFlutterEngine!!.dartExecutor.binaryMessenger, channelName)
        //设置监听Flutter回调原生方法
        mMethodChannel?.setMethodCallHandler { call, result ->
            Log.d(TAG,"call.method = " + call.method + " _argment ; " + call.arguments)
            when (call.method) {
                //原生传递数据给flutter
                "sendDeviceId"->{
                    result.success("1234567890")
                }
                //获取flutter传过来的数据
                "getToken"->{
                    val token = call.argument<String>("token")
                    Log.d(TAG, "token = $token")
                }

                //获取flutter传过来的数据  callHandler的使用, flutter等待回调使用
                "update"->{
//                    val update = call.argument<String>("update")
                    val map = HashMap<String,String>()
                    map.put("words", "words")
                    map.put("imgPath","111111")
                    mMethodChannel?.invokeMethod("updateImage",map)
                }
            }
        }
   }

channelName 为通道名称,可以自己定义,也可以初始化多个通道

其中 setDeviceId 为原生传递给flutter ,通过result.success()传递过去

getToken 为flutter传递给原生数据 ,通过call.argument接收

update 实现 flutter传递给原生数据,原生通过mMethodChannel.invokeMethod 传递对象给flutter层,flutter实现callHandler 等待回调。 即可以理解为,flutter发起事件,原生app执行,原生app执行完回调给flutter,这时flutter 进行callhandler异步接收处理。

flutter 相关代码

getChannelMethodData() {
    //获取原生传递数据
    mc.callBack('sendDeviceId', '', (val) {
      //获取原生传递的唯一设备号;
      print('--->>>原生APP返回的设备号:$val <<<---');
    }).catchError((error) {});

    //主动发送数据给原生
    mc.call('getToken', {'token': "我是一个token"});
  }
Scaffold(
      body: Center(
          child: InkWell(
        onTap: () {
          mc.call('update', {'update': "callHandler"});

          mc.callHandler("updateImage", (result) {
            String words = result['words'];
            String imgPath = result['imgPath'];
            print("=========imgPath=" + imgPath + " words=" + words);
          });
        },
        child: Container(
          width: 200,
          height: 100,
          color: Colors.red,
          child: Text(
            '主动发起回调',
            style: TextStyle(color: Colors.white, fontSize: 16),
          ),
        ),
      )),
    );

二、flutter路由跳转

我们知道 flutter 页面跳转都是依赖widget 跳转。我们可以看到flutter默认MaterialApp就可以设置

routes,进行widget页面管理。

Flutter和原生iOS交互 flutter与安卓原生交互_数据

接下来,我们实现功能从初始化页面跳转到APage,APage->BPage,BPage->CPage,CPage->DPage,然后下面2点功能

1、DPage 返回直接回到初始页面 

2、DPage 返回回到APage,并保留初始页面,

相关代码

Scaffold(
      body: Center(
          child: InkWell(
            onTap: () {
              //移除 除A 其它的页面
              // JumpPage.removeAllOutTargetPage(context, APage());

              ///重点:跳转到APage ,并移除除SplashPage外其它页面
              Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => APage()),
                  ModalRoute.withName(SplashPage.routerName));
            },
            child: Text('DPage'),
          )),
    );

我们可以看到实现第二点功能相比Android实现更加简单

相关代码github:https://github.com/llxqb/TestFlutterEngine.git