Flutter——踩坑之旅(现有Android项目和现有iOS项目引入同一个Flutter项目)

程序猿日常

flutter填坑——现有Android项目和现有iOS项目引入同一个Flutter项目

一.现有Android项目 引入 Flutter 项目(源码Module方法引入)

项目目录
Flutter——踩坑之旅(现有Android项目和现有iOS项目引入同一个Flutter项目)_第1张图片
flutter_module是AndLangBase(Android现有项目)和iOSLangBase(iOS现有项目)引用的同一个flutter module

1.Android Stdio升级至4.0.1版本

2.现有项目升级AndroidX

	distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
	
	classpath 'com.android.tools.build:gradle:3.5.3'
	//butterknife版本升级
	classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0-rc2'
	
	使用自动升级AndroidX功能 Refactor->Migrate to AndroidX

3.创建Flutter Module(flutter_module)

参考链接[https://flutter.cn/docs/development/add-to-app](https://flutter.cn/docs/development/add-to-app)

4.跳转Flutter页面报错

Add-to-app mode got NullPointerException when use BackgroundMode.transparent 

解决:
不使用backgroundMode,注视掉下面代码,跳转flutter页面成功
.backgroundMode(FlutterActivityLaunchConfigs.BackgroundMode.transparent)

5.Flutter继续热更新开发

在flutter module项目的目录下执行命令flutter attach,之后运行app项目,成功之后如下图所示,更新flutter代码时,只有在命令行输入R,就可以实现热更新
Flutter——踩坑之旅(现有Android项目和现有iOS项目引入同一个Flutter项目)_第2张图片

6.原生跳转Flutter页面

两种方式:
1.FlutterEngineCache 在application里提前注册

public static final String FLUTTER_ENGINE_ID="AndLangFlutter";
public static void initFlutter(Context context){
    // Instantiate a FlutterEngine.
    FlutterEngine flutterEngine = new FlutterEngine(context);
    // Configure an initial route.
    flutterEngine.getNavigationChannel().setInitialRoute("/");
    // Start executing Dart code to pre-warm the FlutterEngine.
    flutterEngine.getDartExecutor().executeDartEntrypoint(
            DartExecutor.DartEntrypoint.createDefault()
    );
    // Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
    FlutterEngineCache
            .getInstance()
            .put(FLUTTER_ENGINE_ID, flutterEngine);
}

之后调用方法(注:只能跳转至setInitialRoute的路由地址,无法修改路由)

   activity.startActivity(
                FlutterActivity
                        .withCachedEngine(FLUTTER_ENGINE_ID)
                        .build(activity)
    	);

2.withNewEngine 跳转

	activity.startActivity(
                FlutterActivity
                        .withNewEngine()
                        .initialRoute(route)
                        .build(activity)
        );

工具类FlutterUtil

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterActivityLaunchConfigs;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;

public class FlutterUtil {
 	public static final String FLUTTER_ENGINE_ID="AndLangFlutter";
	public static void initFlutter(Context context){
    // Instantiate a FlutterEngine.
    FlutterEngine flutterEngine = new FlutterEngine(context);
    // Configure an initial route.
    flutterEngine.getNavigationChannel().setInitialRoute("/");
    // Start executing Dart code to pre-warm the FlutterEngine.
    flutterEngine.getDartExecutor().executeDartEntrypoint(
            DartExecutor.DartEntrypoint.createDefault()
    );
    // Cache the FlutterEngine to be used by FlutterActivity or FlutterFragment.
    FlutterEngineCache
            .getInstance()
            .put(FLUTTER_ENGINE_ID, flutterEngine);
	}
	public static void startFlutterActivity(Activity activity,String route){
        if(!BaseLangUtil.isEmpty(route)){
            activity.startActivity(
                    FlutterActivity
                            .withNewEngine()
                            .initialRoute(route)
                            .build(activity)
            );
        }else {
            activity.startActivity(
                    FlutterActivity
                            .withCachedEngine(FLUTTER_ENGINE_ID)
                            .build(activity)
            );
        }
    }
}

二.现有iOS项目 引入 Flutter 项目(源码Module方法引入)

1.引入之前Android生成的Flutter Module

Podfile 中添加下面代码:

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

每个需要集成 Flutter 的 [Podfile target][],执行 install_all_flutter_pods(flutter_application_path)

target 'MyApp' do
	install_all_flutter_pods(flutter_application_path)
end

运行 pod install
这时候可能会报错

[!] No podspec found for `Flutter` in `../flutter_module/.ios/Flutter/engine`

解决办法:
在AndroidStdio中把Flutter Module选择iOS设备运行一次,再pod install 即可解决。

2.踩坑

运行报错: Could not parse callback cache, aborting restore

AppDelegate : FlutterAppDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

return true;
改为:
return [super application:application didFinishLaunchingWithOptions:launchOptions];

3.原生跳转Flutter页面 同Android

工具类FlutterUtil

#import "AppDelegate.h"
#import "FlutterUtil.h"
#import 
#import 
static NSString *FLUTTER_ENGINE_ID=@"iOSLangFlutter";
@implementation FlutterUtil
//获取url中的key的值
+(void)initFlutter{
    ((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine= [[FlutterEngine alloc] initWithName:FLUTTER_ENGINE_ID];
    FlutterEngine *flutterEngine =
    ((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine;
    // Runs the default Dart entrypoint with a default Flutter route.
    [[flutterEngine navigationChannel] invokeMethod:@"setInitialRoute"arguments:@"/"];
    [flutterEngine run];
    // Used to connect plugins (only if you have plugins with iOS platform code).
     [GeneratedPluginRegistrant registerWithRegistry:flutterEngine];
}

+(void)pushFlutterVC:(UIViewController *)vc withRoute:(NSString *)route{
    FlutterViewController *flutterViewController =nil;
    if(![LangUtil isEmpty:route]){
        //设置flutter 路由
        flutterViewController=[[FlutterViewController alloc]init];
        [flutterViewController setInitialRoute:route];
        [GeneratedPluginRegistrant registerWithRegistry:[flutterViewController pluginRegistry]];
    }else{
        FlutterEngine *flutterEngine =
        ((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine;
        flutterViewController =
        [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
    }
    //导航控制器入栈的方式切换页面
     [vc.navigationController pushViewController:flutterViewController animated:YES];
    //模态切换的方式切换页面
    //[vc presentViewController:flutterViewController animated:YES completion:nil];
}
@end

三.看下flutter_module的代码

1.main.dart文件部分代码

import 'package:flutter/material.dart';
import 'dart:ui';
import 'package:flutter_module/common/LogUtil.dart';
import 'package:flutter_module/common/RouteUtil.dart';
void main() {
  LogUtil.showLog("原生传递的参数:"+window.defaultRouteName);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the
        // counter didn't reset back to zero; the application is not restarted.
        primarySwatch: Colors.blue,
      ),
      initialRoute:"/",
      routes:RouteUtil.initRouteMap(context),
      home:initRoute(window.defaultRouteName),
    );
  }
}

方法initRoute中处理接收到Native的参数,返回对应的Widget

2.Flutter页面退出返回到Native页面

if(Platform.isAndroid) {
 	SystemChannels.platform.invokeMethod('SystemNavigator.pop');
}else {
 	 exit(0);
}

你可能感兴趣的:(程序猿日常,ios,android,移动开发,flutter,Android引入,iOS引入)