首页 > 其他分享 >Flutter(六):Flutter_Boost接入现有原生工程(iOS+Android)

Flutter(六):Flutter_Boost接入现有原生工程(iOS+Android)

时间:2022-10-10 17:12:46浏览次数:48  
标签:vc flutter iOS Flutter let install Android options

一、新建原生工程和Flutter Module

1、新建Android工程

搭建一个空的Android工程FlutterDemo_Android模拟已经存在的原有工程
Android项目配置:

2、新建iOS工程

搭建一个空的iOS工程FlutterDemo_iOS模拟已经存在的原有工程
Xcode项目配置

搭建Pod:
在工程目录下执行

pod init
pod install

3、新建Flutter Module

这里使用AndroidStudio做Flutter开发环境

3.1 AndroidStudio添加Flutter插件

3.2 新建Flutter Module

第一步:File -> New Flutter Project

第二步:选择Flutter

第三步:配置Flutter Module

flutter_demo_module

完成目录结构

二、Flutter Boost 配置

1、Flutter_Module工程

1.修改pubspec.yaml文件:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2

  # add
  flutter_boost:  
    git:
      url: 'https://github.com/alibaba/flutter_boost.git'
      ref: '4.1.0'

然后执行flutter pub get下载flutter_boost到module中

2.新增willpop.dart页面做为跳转目标页

import 'package:flutter/material.dart';

class WillPopRoute extends StatefulWidget {
  const WillPopRoute({Key? key, this.title}) : super(key: key);

  final String? title;

  @override
  State<StatefulWidget> createState() => _WillPopRouteState();
}

class _WillPopRouteState extends State<WillPopRoute> {
  bool shouldPop = true;
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        return shouldPop;
      },
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
      ),
    );
  }
}

3.修改main.dart文件,配置页面路由

import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_demo_module/willpop.dart';

void main() {
  CustomFlutterBinding();
  runApp(const MyApp());
}

class CustomFlutterBinding extends WidgetsFlutterBinding
    with BoostFlutterBinding {}


class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
    // 配置路由
  static Map<String, FlutterBoostRouteFactory> routerMap = {
    'flutterPage': (settings, uniqueId) {
      return PageRouteBuilder<dynamic>(
          settings: settings, pageBuilder: (_, __, ___) => const WillPopRoute());
    }
  };

  Route<dynamic>? routeFactory(RouteSettings settings, String? uniqueId) {
    FlutterBoostRouteFactory? func = routerMap[settings.name!];
    if (func == null) {
      return null;
    }
    return func(settings, uniqueId);
  }

  @override
  void initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return FlutterBoostApp(routeFactory);
  }

}

2、Android跳转Flutter:

1.setting.gralde添加:

setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir.parentFile,
        'FlutterDemo_Flutter/.android/include_flutter.groovy'
))
include ':flutter_module'
project(':flutter_module').projectDir = new File('../FlutterDemo_Flutter')

注意:new Binding([gradle: this])会有红色提示,不用管

2.app的AndroidManifest添加:

<activity
    android:name="com.idlefish.flutterboost.containers.FlutterBoostActivity"
    android:theme="@style/Theme.AppCompat"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize" >

</activity>
<meta-data android:name="flutterEmbedding"
    android:value="2">
</meta-data>

注意这一步之后执行gradle sync,如果遇到问题,可以参考文章最后的问题集锦

3.Android跳转代码

val params: Map<String, Any> = HashMap()
val intent: Intent = FlutterBoostActivity.CachedEngineIntentBuilder(
    FlutterBoostActivity::class.java
)
    .backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.opaque)
    .destroyEngineWithActivity(false)
    .url("flutterPage")
    .urlParams(params)
    .build(context)
startActivity(intent)

3、iOS跳转Flutter:

1.修改Pod文件

step1. load file

flutter_application_path = '../flutter_demo_module'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

step2. install function

install_all_flutter_pods(flutter_application_path)

step3 post_install

post_install do |installer|
  flutter_post_install(installer) if defined?(flutter_post_install)
end

完整pod文件

# Flutter Module Path
# step1 load file
flutter_application_path = '../flutter_demo_module'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

target 'FlutterDemo_iOS' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  
  # step2 install function
  install_all_flutter_pods(flutter_application_path)
end

# step3 post_install
post_install do |installer|
  flutter_post_install(installer) if defined?(flutter_post_install)
end

执行pod install,podhelper.rb 脚本会把你的 plugins, Flutter.framework,和 App.framework 集成到你的项目中。

备注:
Flutter.framework 是 Flutter engine 的框架, App.framework 是你的 Dart 代码的编译产物。

2.添加Delegate

定义FlutterDelegate

import UIKit
import Flutter
import flutter_boost
import FlutterPluginRegistrant


class MyBoostAppDelegate: NSObject,FlutterBoostDelegate {
    
    static let shared = MyBoostAppDelegate()

    ///您用来push的导航栏
    var navigationController:UINavigationController?

    ///用来存返回flutter侧返回结果的表
    var resultTable:Dictionary<String,([AnyHashable:Any]?)->Void> = [:];

    func pushNativeRoute(_ pageName: String!, arguments: [AnyHashable : Any]!) {

        //可以用参数来控制是push还是pop
        let isPresent = arguments["isPresent"] as? Bool ?? false
        let isAnimated = arguments["isAnimated"] as? Bool ?? true
        //这里根据pageName来判断生成哪个vc,这里给个默认的了
        let targetViewController = UIViewController()

        if(isPresent){
            self.navigationController?.present(targetViewController, animated: isAnimated, completion: nil)
        }else{
            self.navigationController?.pushViewController(targetViewController, animated: isAnimated)
        }
    }

    func pushFlutterRoute(_ options: FlutterBoostRouteOptions!) {
        let vc:FBFlutterViewContainer = FBFlutterViewContainer()
        vc.setName(options.pageName, uniqueId: options.uniqueId, params: options.arguments,opaque: options.opaque)

        //用参数来控制是push还是pop
        let isPresent = (options.arguments?["isPresent"] as? Bool)  ?? false
        let isAnimated = (options.arguments?["isAnimated"] as? Bool) ?? true

        //对这个页面设置结果
        resultTable[options.pageName] = options.onPageFinished;

        //如果是present模式 ,或者要不透明模式,那么就需要以present模式打开页面
        if(isPresent || !options.opaque){
            self.navigationController?.present(vc, animated: isAnimated, completion: nil)
        }else{
            self.navigationController?.pushViewController(vc, animated: isAnimated)
        }
    }

    func popRoute(_ options: FlutterBoostRouteOptions!) {
        //如果当前被present的vc是container,那么就执行dismiss逻辑
        if let vc = self.navigationController?.presentedViewController as? FBFlutterViewContainer,vc.uniqueIDString() == options.uniqueId{

            //这里分为两种情况,由于UIModalPresentationOverFullScreen下,生命周期显示会有问题
            //所以需要手动调用的场景,从而使下面底部的vc调用viewAppear相关逻辑
            if vc.modalPresentationStyle == .overFullScreen {

                //这里手动beginAppearanceTransition触发页面生命周期
                self.navigationController?.topViewController?.beginAppearanceTransition(true, animated: false)

                vc.dismiss(animated: true) {
                    self.navigationController?.topViewController?.endAppearanceTransition()
                }
            }else{
                //正常场景,直接dismiss
                vc.dismiss(animated: true, completion: nil)
            }
        }else{
            self.navigationController?.popViewController(animated: true)
        }
        //否则直接执行pop逻辑
        //这里在pop的时候将参数带出,并且从结果表中移除
        if let onPageFinshed = resultTable[options.pageName] {
            onPageFinshed(options.arguments)
            resultTable.removeValue(forKey: options.pageName)
        }
    }
}

修改AppDelegate

import UIKit
import flutter_boost

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       
        //创建代理,做初始化操作
        let delegate = MyBoostAppDelegate.shared
        FlutterBoost.instance().setup(application, delegate: delegate) { engine in

        }
        return true
    }
}

跳转Flutter页面代码

    @IBAction func clickButton(_ sender: Any) {
        MyBoostAppDelegate.shared.navigationController = self.navigationController
        let options = FlutterBoostRouteOptions()
        options.pageName = "flutterPage"
        FlutterBoost.instance().open(options)
    }

问题集锦

1.Android导入Flutter Module报错Failed to apply plugin class ‘FlutterPlugin’

setting.gradle修改Model值为RepositoriesMode.PREFER_PROJECT

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
    repositories {
        google()
        mavenCentral()
    }
}

标签:vc,flutter,iOS,Flutter,let,install,Android,options
From: https://www.cnblogs.com/anywherego/p/16776393.html

相关文章

  • android反调试技术
    检测调试相关文件android_server等intSearchFile(){DIR*dir=opendir("/data/local/tmp");if(NULL==dir){return-1;}dirent*file=......
  • flutter系列之:按比例缩放的AspectRatio和FractionallySizedBox
    目录简介AspectRatioFractionallySizedBox总结简介我们在构建UI的时候,为了适应不同的屏幕大小,通常需要进行一些自适应的配置,而最常见的自适应就是根据某个宽度或者高度自......
  • MobPush Android For Unity
    集成准备注册账号使用MobSDK之前,需要先在MobTech官网注册开发者账号,并获取MobTech提供的AppKey和AppSecret,详情可以​​点击查看注册流程​​下载MobPush对应的.unitypackag......
  • Flutter Cocoon 已达到 SLSA 2 级标准的要求
    文/JesseSeales,Dart和Flutter安全工作组工程师今年年初,我们发布了Flutter2022产品路线图,其中「基础设施建设」这部分提到:2022年Flutter团队将增加对供应链的......
  • android hook之ELF hook
    android平台的ELFhook技术LD_PRELOADhooklinker程序在对elf可执行程序进行重定位时会根据so库加载的顺序去寻找对应导出符号。利用LD_PRELOAD优先加载自定义的so库并......
  • iostat命令
    一、概述iostat主要用于输出磁盘IO和CPU的统计信息iostat属于sysstat软件包,可以用yum installsysstat直接安装二、iostat用法1、用法:iostat[选项][<时间间隔>......
  • Axios 取消重复请求
    在实际开发中,我们需要对用户发起的重复请求进行拦截处理,比如用户快速点击提交按钮解决办法1、新建request.jsimportaxiosfrom'axios'//创建axios实例constse......
  • 调整 FMX Android 文字显示「锯齿」效果
    说明:调整FiremonkeyAndroid显示文字有「锯齿」效果适用:FiremonkeyAndroid平台修改方法:请将源码FMX.FontGlyphs.Android.pas 复制到自己的工程目录里,再进行修改。......
  • Vue3使用axios
    如何在Vue项目中使用axios请求http://www.45fan.com/article.php?aid=1D82KNnQB62JUc6OVue3-使用axios发起网络请求https://blog.csdn.net/liuyuxin36/article/details/......
  • axios取消上一个请求
      链接,里面有效果,亲测有效果https://codesandbox.io/s/simple-example-of-cancelling-axios-request-kyrnc?file=/src/App.vue:1074-1096这个可能需要外网才能打开,要......