TitanFlutter

新一代Flutter-Native混合解决方案。 TitanFlutter是一个Flutter插件,它可以轻松地为现有原生应用程序提供Flutter混合集成方案。TitanFlutter的理念是将Flutter像Webview那样来使用。在现有应用程序中同时管理Native页面和Flutter页面并非易事。 TitanFlutter帮你处理页面的映射和跳转,你只需关心页面的名字和参数即可(通常可以是URL)。

前置条件

在继续之前,您需要将Flutter集成到你现有的项目中。

  1. 如果你要集成需要把example/android/app/build.gradle 中isLib改成 true,当然默认为true,其次如果要uploadArchives ,你只需要执行根目录uploadArchives.sh文件即可。
  2. 如果你要运行该项目需要把example/android/app/build.gradle 中isLib改成false。

安装

在 Android 项目中添加依赖.

  1. 打开项目根目录并且编辑 gradle.property文件 // titanflutter TITANFLUTTER_VERSION=1.0.0 titanflutterModule=aar

  2. 打开项目根目录并且编辑 app/build.gradle文件 // titanflutter if (titanflutterModule.equals("aar")) { compile "com.meiyou:titanflutter:${TITANFLUTTER_VERSION}" } else { compile project(":titanflutter") }

  3. 打开项目根目录并且编辑 app/build.gradle文件,在buildTypes同级加上如下配置,否则编译会出现:More than one file was found with OS independent path 'lib/armeabi-v7a/libflutter.so' 错误

    packagingOptions { pickFirst 'lib/x86/libflutter.so' pickFirst 'lib/armeabi-v7a/libflutter.so' pickFirst 'lib/arm64-v8a/libflutter.so' pickFirst 'lib/armeabi/libflutter.so' }

  4. 当Android项目中的Application没有继承FlutterApplication时会出现 Caused by: java.lang.IllegalStateException: ensureInitializationComplete must be called after startInitialization 崩溃错误,修复如下: 4.1:让Android项目中的Application继承FlutterApplication,建议使用该方案。 4.2:如果不使用第一种方案,可以在MainActivity的onCreate函数中的super.onCreate之前加上:FlutterMain.startInitialization(getApplicationContext()); 其次在MainActivity的onCreate函数中加上如下初始化的代码: TitanFlutterPlugin.init(new IPlatform() { @Override public Application getApplication() { return MainActivity.this.getApplication(); }

                    /**
                     * 获取应用入口的Activity,这个Activity在应用交互期间应该是一直在栈底的
                     * @return
                     */
                    @Override
                    public Activity getMainActivity() {
                        if (MainActivity.sRef != null) {
                            return MainActivity.sRef.get();
                        }
    
                        return null;
                    }
    
                    @Override
                    public boolean isDebug() {
                        return true;
                    }
    
                    /**
                     * 如果flutter想打开一个本地页面,将会回调这个方法,页面参数将会拼接在url中
                     *
                     * 例如:sample://nativePage?aaa=bbb
                     *
                     * 参数就是类似 aaa=bbb 这样的键值对
                     *
                     * @param context
                     * @param url
                     * @param requestCode
                     * @return
                     */
                    @Override
                    public boolean startActivity(Context context, String url, int requestCode) {
                        Debuger.log("startActivity url="+url);
    
                        return PageRouter.openPageByUrl(context,url,requestCode);
                    }
    
                    @Override
                    public Map getSettings() {
                        return null;
                    }
                });
    

在Flutter项目中添加依赖项。

打开pubspec.yaml并将以下行添加到依赖项:

titanflutter: ^1.0.4

Dart代码的集成

将init代码添加到App App

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();

    ///register page widget builders,the key is pageName
    TitanFlutter.singleton.registerPageBuilders({
      'sample://firstPage': (pageName, params, _) => FirstRouteWidget(),
      'sample://secondPage': (pageName, params, _) => SecondRouteWidget(),
    });

    ///query current top page and load it
    TitanFlutter.handleOnStartPage();
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
      title: 'TitanFlutter example',
      builder: TitanFlutter.init(), ///init container manager
      home: Container());
}

iOS代码集成。

注意:需要将libc++ 加入 "Linked Frameworks and Libraries" 中。

使用FLBFlutterAppDelegate作为AppDelegate的超类

@interface AppDelegate : FLBFlutterAppDelegate <UIApplicationDelegate>
@end

为您的应用程序实现FLBPlatform协议方法。

@interface DemoRouter : NSObject<FLBPlatform>

@property (nonatomic,strong) UINavigationController *navigationController;

+ (DemoRouter *)sharedRouter;

@end


@implementation DemoRouter

- (void)openPage:(NSString *)name
          params:(NSDictionary *)params
        animated:(BOOL)animated
      completion:(void (^)(BOOL))completion
{
    if([params[@"present"] boolValue]){
        FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
        [vc setName:name params:params];
        [self.navigationController presentViewController:vc animated:animated completion:^{}];
    }else{
        FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
        [vc setName:name params:params];
        [self.navigationController pushViewController:vc animated:animated];
    }
}


- (void)closePage:(NSString *)uid animated:(BOOL)animated params:(NSDictionary *)params completion:(void (^)(BOOL))completion
{
    FLBFlutterViewContainer *vc = (id)self.navigationController.presentedViewController;
    if([vc isKindOfClass:FLBFlutterViewContainer.class] && [vc.uniqueIDString isEqual: uid]){
        [vc dismissViewControllerAnimated:animated completion:^{}];
    }else{
        [self.navigationController popViewControllerAnimated:animated];
    }
}

@end

在应用程序开头使用FLBPlatform初始化TitanFlutter。

 [TitanFlutterPlugin.sharedInstance startFlutterWithPlatform:router
                                                        onStart:^(FlutterViewController * fvc){
                                                            
                                                        }];

Android代码集成。

在Application.onCreate()中初始化TitanFlutter

public class MyApplication extends FlutterApplication {
    @Override
    public void onCreate() {
        super.onCreate();
        TitanFlutterPlugin.init(new IPlatform() {
            @Override
            public Application getApplication() {
                return MyApplication.this;
            }

            /**
             * get the main activity, this activity should always at the bottom of task stack.
             */
            @Override
            public Activity getMainActivity() {
                return MainActivity.sRef.get();
            }

            @Override
            public boolean isDebug() {
                return false;
            }

            /**
             * start a new activity from flutter page, you may need a activity router.
             */
            @Override
            public boolean startActivity(Context context, String url, int requestCode) {
                return PageRouter.openPageByUrl(context,url,requestCode);
            }

            @Override
            public Map getSettings() {
                return null;
            }
        });
    }

基本用法

概念

所有页面路由请求都将发送到Native路由器。Native路由器与Native Container Manager通信,Native Container Manager负责构建和销毁Native Containers。

使用titan Flutter Native Container用Native代码打开Flutter页面。

 FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
        [vc setName:name params:params];
        [self.navigationController presentViewController:vc animated:animated completion:^{}];

Android

public class FlutterPageActivity extends TitanFlutterActivity {

    @Override
    public void onRegisterPlugins(PluginRegistry registry) {
        //register flutter plugins
        GeneratedPluginRegistrant.registerWith(registry);
    }

    @Override
    public String getContainerName() {
        //specify the page name register in TitanFlutter
        return "sample://firstPage";
    }

    @Override
    public Map getContainerParams() {
        //params of the page
        Map<String,String> params = new HashMap<>();
        params.put("key","value");
        return params;
    }
}

或者用Fragment

public class FlutterFragment extends TitanFlutterFragment {
    @Override
    public void onRegisterPlugins(PluginRegistry registry) {
        GeneratedPluginRegistrant.registerWith(registry);
    }

    @Override
    public String getContainerName() {
        return "sample://firstPage";
    }

    @Override
    public Map getContainerParams() {
        Map<String,String> params = new HashMap<>();
        params.put("key","value");
        return params;
    }
}

使用TitanFlutter在dart代码打开页面。

Dart

 TitanFlutter.singleton.openPage("pagename", {}, true);

使用TitanFlutter在dart代码关闭页面。

TitanFlutter.singleton.closePageForContext(context);

Examples

更详细的使用例子请参考Demo

作者

hechaohua@xiaoyouzi.com

许可证

该项目根据MIT许可证授权 - 有关详细信息,请参阅LICENSE.md(LICENSE.md)文件

致谢

  • Flutter

Libraries

boost_container
boost_page_route
container_coordinator
container_manager
logger
message_proxy
native_page_container_event_handler
observers_holders
page_result_mediator
router
service_loader
titanflutter
tracer