kotlin中使用Flutter-Boost混合开发的传值跳转问题

使用场景

  • 对于一些业务功能单一或者只是用来展示而没有过多交互的页面,比如登录页面或者商品列表页,只是为了给用户展示,这种页面有时候为了Android和iOS节省开发时间,没有必要Android和iOS各搞一套,考虑使用flutter去绘制这些页面,然后再native端都依赖此flutter module,从而提高项目进展速度,本文使用闲鱼开源的flutter-boost在kotlin下进行实现
  • 使用flutter-boost版本
  • flutter_boost: ^1.12.13+1

目录结构

Android工程集成flutter-boost

  • 在Android project同级目录下新建flutter moudle项,让你的app moudle依赖flutter moudle
  • pubspec.yaml 中引入flutter-boost依赖
  cupertino_icons: ^0.1.2
  flutter_boost: ^1.12.13+1

flutter moudle中使用flutter-boost

  • 在入口文件(main.dart) 将flutter中的每个widget以键值对的形式注册进FlutterBoost
  • 将flutter中的每个widget以键值对的形式注册进FlutterBoost
  • 原生端可通过 下方’flutterPage’这个key去路由到指定Widget页面FlutterRouteWidget
class MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    FlutterBoost.singleton.registerPageBuilders({
      'flutterPage': (pageName, params, _) {
        print("flutterPage params:$params");
        return FlutterRouteWidget(params:params);
      },
    });
    FlutterBoost.singleton.addBoostNavigatorObserver(TestBoostNavigatorObserver());
  }
class TestBoostNavigatorObserver extends NavigatorObserver{
  void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {

    print("flutterboost#didPush");
  }

  void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
    print("flutterboost#didPop");
  }

  void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) {
    print("flutterboost#didRemove");
  }

  void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
    print("flutterboost#didReplace");
  }
}

Android Native端注册 flutter-boost

  • Application中FlutterBoost初始化
 private fun initFlutterBoost() {

        val router =
            INativeRouter { context, url, urlParams, requestCode, exts ->
                val assembleUrl: String = Utils.assembleUrl(url, urlParams)
                openPageByUrl(context, assembleUrl, urlParams)
            }

        val boostLifecycleListener: BoostLifecycleListener = object : BoostLifecycleListener {
            override fun onEngineCreated() {}
            override fun onPluginsRegistered() {}
            override fun beforeCreateEngine() {}
            override fun onEngineDestroy() {}
        }
        
        val platform = FlutterBoost.ConfigBuilder(this, router)
            .isDebug(true)
            .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
            .renderMode(FlutterView.RenderMode.texture)
            .lifecycleListener(boostLifecycleListener)
            .build()
        FlutterBoost.instance().init(platform)
    }
  • AndroidManifest配置
  • 说明
 // AndroidManifest.xml 中必须要添加 flutterEmbedding 版本设置
        //
        //   <meta-data android:name="flutterEmbedding"
        //               android:value="2">
        //    </meta-data>
        // GeneratedPluginRegistrant 会自动生成 新的插件方式 
        //
        // 插件注册方式请使用
        // FlutterBoost.instance().engineProvider().getPlugins().add(new FlutterPlugin());
        // GeneratedPluginRegistrant.registerWith(),是在engine 创建后马上执行,放射形式调用
        //
  • 本例配置参考
 <activity android:name=".NativePageActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:windowSoftInputMode="adjustResize"/>
             <meta-data
                    android:name="flutterEmbedding"
                    android:value="2">
        </meta-data>
      
        <activity android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"
            android:theme="@style/Theme.AppCompat"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize" >
            <meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable" android:resource="@drawable/page_loading"/>

        </activity>

Android跳转Flutter传参

  • 顶层函数文件 PageRoute
package com.bliss.fktapp

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.util.Log
import com.idlefish.flutterboost.containers.BoostFlutterActivity

/**
 * @Author yangtianfu
 * @CreateTime 2020/4/17 20:39
 * @Describe 是我们原生定义顶层的一个页面路由类 处理Flutter页面根据url打开另一个页面
 */
// flutter 跳转Android的URL
val NATIVE_PAGE_URL = "sample://nativePage"
//  android跳转flutter的URL
val FLUTTER_PAGE_URL = "sample://flutterPage"
//只读map集合存放路由名字
val pageName = mapOf(
    "sample://flutterPage" to "flutterPage"
)

fun openPageByUrl(
    context: Context,
    url: String,
    params: Map<*, *>?
): Boolean {
    return openPageByUrl(context, url, params, 0)
}

fun openPageByUrl(
    context: Context,
    url: String,
    params: Map<*, *>?,
    requestCode: Int
): Boolean {
    val path = url.split("\\?").toTypedArray()[0]
//    从flutter过来的页面会走这里去匹配跳转对应的activity,同时携带必要参数
//    openPageByUrl ==: sample://nativePage?from=Flutter
    Log.i("openPageByUrl == ", path)
    return try {
        if (pageName.containsKey(path)) {
            Log.i("路由至Flutter页面 == ", path)
            val intent =
                BoostFlutterActivity.withNewEngine().url(pageName[path]!!).params(params!!)
                    .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque).build(context)
            if (context is Activity) {
                context.startActivityForResult(intent, requestCode)
            } else {
                context.startActivity(intent)
            }
            return true
        } else if (url.startsWith(NATIVE_PAGE_URL)) {
            if (url.contains("?")){
                //  从Flutter过来的页面携带参数
                var intent = Intent(context, NativePageActivity::class.java)
                   intent.putExtra("url",url)
                context.startActivity(intent)
            }else{
//                从Flutter过来的页面没有携带参数
                context.startActivity(Intent(context, NativePageActivity::class.java))
            }
            return true
        } else{
            Log.i("路由未知页面 == ", path)
            Log.e("key", pageName.keys.toString())
        }
        false
    } catch (t: Throwable) {
        false
    }
}


  • Android携参数跳转flutter
  var map = mapOf(
            "name" to "bliss",
            "sex" to "男"
        )
        
  when(v){
            //Android内部跳转
            open_native -> openPageByUrl(this, NATIVE_PAGE_URL,map)
            //Android携参数跳转flutter
            open_flutter -> openPageByUrl(this, FLUTTER_PAGE_URL,map)
        }
  • flutter获取原生传来的参数信息
 //获取原生传来的参数信息
    final String message=widget.message;
  • 效果图

  • 完整flutter页面参考

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
// 原生路由至此页面
class FlutterRouteWidget extends StatefulWidget {
  final Map params;
  final String message;

  //可选参数构造函数
  FlutterRouteWidget({this.params,this.message});

  @override
  _FlutterRouteWidgetState createState()=>_FlutterRouteWidgetState();

}

class _FlutterRouteWidgetState extends State<FlutterRouteWidget>{
  final TextEditingController _usernameController = TextEditingController();
  @override
  Widget build(BuildContext context) {
    //获取原生传来的参数信息
    final String message=widget.message;

    return Scaffold(
      appBar: AppBar(
        brightness: Brightness.light,
        backgroundColor: Colors.white,
        textTheme: new TextTheme(title: TextStyle(color: Colors.black)),
        title: Text('Flutter Boost'),
      ),
      body: SingleChildScrollView(
        child: Container(
          margin: const EdgeInsets.all(24.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Container(
                margin: const EdgeInsets.only(top: 10.0,bottom: 20.0),
                alignment: AlignmentDirectional.center,
                child: Text(
                  message ?? "flutter页面接收到Android参数\n :${widget.params}",
                  style: TextStyle(fontSize: 20.0,color: Colors.blue),
                ),
              ),
              const CupertinoTextField(
                prefix: Icon(
                  CupertinoIcons.person_solid,
                  color: CupertinoColors.lightBackgroundGray,
                  size: 28.0,
                ),
                padding: EdgeInsets.symmetric(horizontal: 6.0,vertical: 12.0),
                clearButtonMode: OverlayVisibilityMode.editing,
                textCapitalization: TextCapitalization.words,
                autocorrect: false,
                decoration: BoxDecoration(
                  border: Border(bottom: BorderSide(width: 0.0,color: CupertinoColors.inactiveGray))
                ),
                placeholder: 'Name',
              ),
              InkWell(
                child:  Container(
                  padding: const EdgeInsets.all(8.0),
                  margin: const EdgeInsets.all(8.0),
                  color: Colors.yellow,
                  child: Text(
                    'Flutter带参数跳转原生',
                    style: TextStyle(fontSize: 22.0, color: Colors.black),
                  ),
                ),
                onTap: ()=> FlutterBoost.singleton.open("sample://nativePage",urlParams:  <dynamic,dynamic>{
                  "query": {"from": "\n Come From Flutter"}
                }),
              ),
              InkWell(
                child: Container(
                    padding: const EdgeInsets.all(8.0),
                    margin: const EdgeInsets.all(8.0),
                    color: Colors.yellow,
                    child: Text(
                      'Flutter 跳转 Flutter',
                      style: TextStyle(fontSize: 22.0, color: Colors.black),
                    )),
                onTap: () {
                  Navigator.push<dynamic>(context,
                      MaterialPageRoute<dynamic>(builder: (_) => PushWidget()));
                },
              ),

            ],
          ),
        ),
      ),
    );
  }
}

class PushWidget extends StatefulWidget{
  @override
  _PushWidgetState createState() => _PushWidgetState();
  }

class _PushWidgetState extends State<PushWidget>{
  VoidCallback _backPressedListenerUnsub;

  @override
  Widget build(BuildContext context) {
    return FlutterRouteWidget(message:"Flutter 有状态 Widget");
  }

  @override
  void dispose() {
    print('[XDEBUG] - PushWidget is disposing~');
    super.dispose();
    _backPressedListenerUnsub?.call();
  }
}

Flutter跳转Android传参

  • flutter点击跳转原生
  • 下方onTap方法
 InkWell(
                child:  Container(
                  padding: const EdgeInsets.all(8.0),
                  margin: const EdgeInsets.all(8.0),
                  color: Colors.yellow,
                  child: Text(
                    'Flutter带参数跳转原生',
                    style: TextStyle(fontSize: 22.0, color: Colors.black),
                  ),
                ),
                onTap: ()=> FlutterBoost.singleton.open("sample://nativePage",urlParams:  <dynamic,dynamic>{
                  "query": {"from": "\n Come From Flutter"}
                }),
              ),
  • Android接收Flutter的参数
  • 通过上述跳转时候的key sample://nativePage来匹配跳转未知,具体方式在上文顶层函数文件中
 if (url.contains("?")){
                //  从Flutter过来的页面携带参数
                var intent = Intent(context, NativePageActivity::class.java)
                   intent.putExtra("url",url)
                context.startActivity(intent)
            }else{
//                从Flutter过来的页面没有携带参数
                context.startActivity(Intent(context, NativePageActivity::class.java))
            }
  • 效果图

源码链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值