Flutter mixed-use development

Mixed-use development Introduction

App developed from scratch using the Flutter is a relaxing thing, but for some mature products, completely abandoned the original App of the history of precipitation, a comprehensive shift Flutter is unrealistic. Therefore, the use of Flutter to unify Android, iOS technology stack, put it as an extension of the existing capabilities of the native App, developed to enhance the efficiency of the mobile terminal through an orderly way.
At present, the page you want to embed some Flutter existing native App where there are two options. One is the original student works as a sub-project engineering Flutter, Flutter by the unified management, this mode is called unified management model. Flutter is another submodule works as a native engineering, maintain the original native engineering change management, this model is called a three-terminal split mode.

Here Insert Picture Description
Flutter occurs early in the frame, due to the mixed mode and the limited information provided by the official, the earliest use of Flutter mixed use development team is mostly unified management model. However, with the deepening of business iteration, the drawbacks of unified management model also will reveal not only the three-terminal (Android, iOS and Flutter) codes coupled serious, time-consuming tools chain also will be a substantial increase, ultimately resulting in reduced development efficiency. Therefore, the subsequent use of the Flutter mixed development team mostly uses three separate mode-side code to dependency management, and ultimately lightweight access Flutter project.
In addition to access to the outer lightweight, three-side code pattern may also be separated as a sub-module to module Flutter native project, thereby rapidly Flutter access module, reducing costs native renovation project. Upon completion of the access module for Flutter, Flutter Android Studio project can be used for development, no longer need to open the original project can be developed for Dart debugging code and native code.
The key to using separate three terminal mode is detached Flutter Flutter mixed engineering development, the product was constructed in accordance with the different platforms to be managed in the form of standard components, i.e. the use of Android aar, iOS used pod. In other words, Flutter hashing scheme is actually packaged into the Flutter module or pod aar library, and then works like a native refer to other third-party native component library that can be introduced in the Flutter module.

Flutter module

By default, Flutter project will include the newly created directory and directory Flutter native projects. In this case, the project will depend on Flutter native libraries and engineering resources, and can not escape Flutter works independently build and run.
In the mixed-use development, the primary dependence on Flutter project is divided into two parts. Flutter is a library and an engine, comprising a main engine and Flutter Framework libraries of libraries; Flutter module is further engineering, i.e. mixed Development Flutter Flutter function module, including Dart project under the code Flutter lib directory implementation.
For the original project, the integration Flutter Flutter only need to create a module in the same directory, then build their own iOS and Android Flutter dependent libraries can be. Next, we just need the same level in the original project directory, execute the command module provides building Flutter Flutter creation module, as shown below.

flutter create -t module flutter_library    

Which, flutter_library as Flutter module name. After executing the above command will generate a flutter_library module works in the same directory of the original project. Flutter Flutter module also works using Android Studio open it, its directory as shown below.
Here Insert Picture Description
It can be seen and engineering compared to ordinary Flutter, Flutter module project also embedded Android and iOS engineering works, but by default, Android and iOS engineering works are hidden. Thus, for Flutter module project, the project can be as ordinary as using Android Studio for development and debugging.
At the same time, compared to ordinary Flutter works under Android project directory Flutter module project more than a Flutter directory, build.gradle configuration of this directory is that we build packaged configuration when aar. Similarly, the module will be found under the Flutter engineering project directory iOS a Flutter directory, which is like Flutter Flutter module works both as general engineering development using Android Studio to debug, but also packed a reason to build aar or pod.

Android integration Flutter

Flutter integrated in the native Android project, the project dependency on native Flutter mainly includes two parts, which are Flutter libraries and engines, and Flutter engineered product.

  • Flutter libraries and engines: Contains icudtl.dat, libFlutter.so and some class files, these files will eventually be packaged into Flutter.jar in.
  • Flutter engineering products: includes application data segment isolate_snapshot_data, application instructions section isolate_snapshot_instr, virtual machine data segment vm_snapshot_data, virtual machine instructions segment vm_snapshot_instr and resource files flutter_assets.

和原生Android工程集成其他插件库的方式一样,在原生Android工程中引入Flutter模块需要先在settings.gradle中添加如下代码。

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

其中,flutter_library为我们创建的Flutter模块。然后,在原生Android工程的app目录的build.gradle文件中添加如下依赖。

dependencies {
	implementation project(":flutter")
}

然后编译并运行原生Android工程,如果没有任何错误则说明集成Flutter模块成功。需要说明的是,由于Flutter支持的最低版本为16,所以需要将Android项目的minSdkVersion修改为16。
如果出现“程序包android.support.annotation不存在”的错误,需要使用如下的命令来创建Flutter模块,因为最新版本的Android默认使用androidx来管理包。

flutter create --androidx -t module flutter_library

对于Android原生工程,如果还没有升级到androidx,可以在原生Android工程上右键,然后依次选择【Refactor】→【Migrate to Androidx】将Android工程升级到androidx包管理。
在原生Android工程中成功添加Flutter模块依赖后,打开原生Android工程,并在应用的入口MainActivity文件中添加如下代码。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View flutterView = Flutter.createView(this, getLifecycle(), "route1");
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        addContentView(flutterView, layoutParams);
    }
}

通过Flutter提供的createView()方法,可以将Flutter页面构建成Android能够识别的视图,然后将这个视图使用Android提供的addContentView()方法添加到父窗口即可。重新运行原生Android工程,最终效果如下图所示。
Here Insert Picture Description
如果原生Android的MainActivity加载的是一个FrameLayout,那么加载只需要将Flutter页面构建成一个Fragment即可,如下所示。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentTransaction ft= getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.fragment_container, Flutter.createFragment("Hello Flutter"));
        ft.commit();
    }
}

除了使用Flutter模块方式集成外,还可以将Flutter模块打包成aar,然后再添加依赖。在flutter_library根目录下执行aar打包构建命令即可抽取Flutter依赖,如下所示。

flutter build apk --debug

此命令的作用是将Flutter库和引擎以及工程产物编译成一个aar包,上面命令编译的aar包是debug版本,如果需要构建release版本,只需要把命令中的debug换成release即可。
打包构建的flutter-debug.aar位于.android/Flutter/build/outputs/aar/目录下,可以把它拷贝到原生Android工程的app/libs目录下,然后在原生Android工程的app目录的打包配置build.gradle中添加对它的依赖,如下所示。

dependencies {
  implementation(name: 'flutter-debug', ext: 'aar')   
}

然后重新编译一下项目,如果没有任何错误提示则说明Flutter模块被成功集成到Android原生工程中。

iOS集成Flutter

原生iOS工程对Flutter的依赖包含Flutter库和引擎,以及Flutter工程编译产物。其中,Flutter 库和引擎指的是Flutter.framework等,Flutter工程编译产物指的是 App.framework等。
在原生iOS工程中集成Flutter需要先配置好CocoaPods,CocoaPods是iOS的类库管理工具,用来管理第三方开源库。在原生iOS工程中执行pod init命令创建一个Podfile文件,然后在Podfile文件中添加Flutter模块依赖,如下所示。

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

target 'iOSDemo' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  install_all_flutter_pods(flutter_application_path)

  # Pods for iOSDemo
  … //省略其他脚本
end '

然后,关闭原生iOS工程,并在原生iOS工程的根目录执行pod install命令安装所需的依赖包。安装完成后,使用Xcode打开iOSDemo.xcworkspace原生工程。
默认情况下,Flutter是不支持Bitcode的,Bitcode是一种iOS编译程序的中间代码,在原生iOS工程中集成Flutter需要禁用Bitcode。在Xcode中依次选择【TAGETS】→【Build Setttings】→【Build Options】→【Enable Bitcode】来禁用Bitcode,如下图所示。
Here Insert Picture Description
如果使用的是Flutter早期的版本,还需要添加build phase来支持构建Dart代码。依次选择【TAGGETS】→【Build Settings】→【Enable Phases】,然后点击左上角的加号新建一个“New Run Script Phase”,添加如下脚本代码。

"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed

不过,最新版本的Flutter已经不需要再添加脚本了。重新运行原生iOS工程,如果没有任何错误则说明iOS成功集成Flutter模块。
除了使用Flutter模块方式外,还可以将Flutter模块打包成可以依赖的动态库,然后再使用CocoaPods添加动态库。首先,在flutter_library根目录下执行打包构建命令生成framework动态库,如下所示。

flutter build ios --debug

上面命令是将Flutter工程编译成Flutter.framework和App.framework动态库。如果要生成release版本,只需要把命令中的debug换成release即可。
然后,在原生iOS工程的根目录下创建一个名为FlutterEngine的目录,并把生成的两个framework动态库文件拷贝进去。不过,iOS生成模块化产物要比Android多一个步骤,因为需要把Flutter工程编译生成的库手动封装成一个pod。首先,在flutter_ library该目录下创建FlutterEngine.podspec,然后添加如下脚本代码。

Pod::Spec.new do |s|
  s.name             = 'FlutterEngine'
  s.version          = '0.1.0'
  s.summary          = 'FlutterEngine'
  s.description      = <<-DESC
TODO: Add long description of the pod here.
                       DESC
  s.homepage         = 'https://github.com/xx/FlutterEngine'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'xzh' => '[email protected]' }
  s.source       = { :git => "", :tag => "#{s.version}" }
  s.ios.deployment_target = '9.0'
  s.ios.vendored_frameworks = 'App.framework', 'Flutter.framework'
end

然后,执行pod lib lint命令即可拉取Flutter模块所需的组件。接下来,在原生iOS工程的Podfile文件添加生成的库即可。

target 'iOSDemo' do
    pod 'FlutterEngine', :path => './'
end

重新执行pod install命令安装依赖库,原生iOS工程集成Flutter模块就完成了。接下来,使用Xcode打开ViewController.m文件,然后添加如下代码。

#import "ViewController.h"
#import <Flutter/Flutter.h>
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *button = [[UIButton alloc]init];
    [button setTitle:@"加载Flutter模块" forState:UIControlStateNormal];
    button.backgroundColor=[UIColor redColor];
    button.frame = CGRectMake(50, 50, 200, 100);
    [button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
    [button addTarget:self action:@selector(buttonPrint) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)buttonPrint{
    FlutterViewController * flutterVC = [[FlutterViewController alloc]init];
    [flutterVC setInitialRoute:@"defaultRoute"];
    [self presentViewController:flutterVC animated:true completion:nil];
}

@end

在上面的代码中,我们在原生iOS中创建了一个按钮,点击按钮时就会跳转到Flutter页面,最终效果如下图所示。
Here Insert Picture Description
默认情况下,Flutter为提供了两种调用方式,分别是FlutterViewController和FlutterEngine。对于FlutterViewController来说,打开ViewController.m文件,在里面添加一个加载flutter页面的方法并且添加一个按钮看来调用。

Flutter模块调试

As we all know, one of the advantages Flutter is to use thermal overload function in the development process to achieve fast commissioning. By default, the original project after Flutter module integrated thermal overload functions are disabled, need to re-run the original project to see the results. Thus, Flutter developed thermal overload advantage is lost, and development efficiency decreases.
So, you can open it in thermal overload Flutter mixed project? The answer is yes, only need to go through the following steps to turn on the hot reload function. First, turn off native applications, where said closing means close the application process, rather than simply exit the application. Input flutter attach Flutter commands at the root module, and the native application is opened again, will see a prompt connection is successful, as shown in FIG.

Here Insert Picture Description
If both multiple devices may be used flutter attach -d command to specify the device connected. Next, simply press button r performing a thermal overload, press R to perform a warm reboot, disconnect button press d.
In Flutter works, we can click on a button to debug code debugging, but in a mixed project, just click the debug button does not work. In this case, the use of the attach button flutter Android Studio provided to establish a connection with the module flutter, flutter performed to realize debugging of code modules, as shown below in FIG.

Here Insert Picture Description
The above are just done introducing Flutter module in the native project, you will encounter communication problems with the Flutter module when specific development, route management, and packaging and so on.

Published 999 original articles · won praise 1976 · Views 4.09 million +

Guess you like

Origin blog.csdn.net/xiangzhihong8/article/details/104059070