gfaraday / g_faraday

A plugin for building hybrid stack apps with flutter
MIT License
143 stars 21 forks source link
android dart faraday flutter flutter-boost ios kotlin swift

log Faraday English

Build pub_Version Flutter_Version License

一个Flutter混合栈开发解决方案

Features

使用g_faraday的APP

序号 名称 版本号 iOS Android
0 寓小二 8.0.0 AppStore 应用宝

您的app也在使用?联系我们

Show Cases

demo

Example App

Android下载apk

设计原则

更新策略

_Flutter stable channel 发布后 一周内适配发布对应的g_faraday版本_

Requirements

版本对应关系

g_faraday flutter cocoapods remark
^1.0.0 Flutter 3.0.5 • channel stable • https://github.com/flutter/flutter.git any recommend
^1.0.0-beta.1 Flutter 3.0.3 • channel stable • https://github.com/flutter/flutter.git any not recommend
^0.7.2 Flutter 2.5.0 • channel stable • https://github.com/flutter/flutter.git any not recommend
^0.7.0 Flutter 2.0.0 • channel stable any not recommend
^0.5.1-nullsafety.0 Flutter 1.24.0-10.2.pre • channel beta any not recommend
^0.5.0-nullsafety.0 Flutter 1.24.0-10.2.pre • channel beta any not recommend
^0.4.0 Flutter 1.24.0-10.2.pre • channel beta any not recommend

快速开始

如果您已经有其他类似框架使用经验,可以直接查看Example浏览最佳实践。

run example project: flutter run --no-sound-null-safety

添加依赖

dependencies:
  g_faraday: ^0.7.0

Flutter 端集成

flutter侧的集成工作,主要是注册需要从原生打开的页面。


// 0x00 定义 route
final route = faraday.wrapper((settings) {
    switch (settings.name) {
    case 'first_page':
        return CupertinoPageRoute(builder: (context) => Text('First Page'));
    case 'second_page':
        return CupertinoPageRoute(builder: (context) => Text('Second Page'));
    }
    return CupertinoPageRoute(builder: (context) => Text(settings.name));
});

// 0x01 将 route 赋给你的app widget
CupertinoApp(onGenerateRoute: (_) => route);

// 0x02 flutter 侧集成完毕,接下来你可以选择 集成iOS/Android

注意不管是CupertinoApp还是MaterialApp都不要设置home

iOS 集成

Objective-C集成看这里

为了实现从Flutter端打开原生页面的应用场景,所以我们需要实现一个打开原生页面的protocol


// 0x00 实现 `FaradayNavigationDelegate`
extension AppDelegate: FaradayNavigationDelegate {

    func push(_ name: String, arguments: Any?, options: [String : Any]?, callback token: CallbackToken) {

        let isFlutter = options?["flutter"] as? Bool ?? false
        let isPresent = options?["present"] as? Bool ?? false

        let vc = isFlutter ? FaradayFlutterViewController(name, arguments: arguments) : FirstViewController(name, arguments: arguments)

        let topMost = UIViewController.fa.topMost
        if (isPresent) {
            // 此处注意
            // vc.modalPresentationStyle 不能是`pageSheet`
            // 如果的确需要这种UI效果,可以配合透明背景,在Flutter侧实现
            topMost?.present(vc, animated: true, completion: nil)
        } else {
            topMost?.navigationController?.pushViewController(vc, animated: true)
        }

        // 非常重要
        // 如果此处不调用 `enableCallback` 那么flutter侧`await Navigator`则永远不会返回
        vc.fa.enableCallback(with: token)
    }
}

// 0x01 在 `application: didFinishLaunchingWithOptions`中启动flutter engine
Faraday.default.startFlutterEngine(navigatorDelegate: self)

// 0x02 打开一个flutter 页面
let vc = FaradayFlutterViewController("first_page", arguments: nil)
navigationController?.pushViewController(vc, animated: true)

// 0x03 集成完毕

Android 集成

为了实现从Flutter端打开原生页面的应用场景,所以我们需要实现一组打开原生页面的接口


// 0x00 实现 navigator
class SimpleFlutterNavigator : FaradayNavigator {

    companion object {
        const val KEY_ARGS = "_args"
    }

    override fun create(name: String, arguments: Serializable?, options: HashMap<String, *>?): Intent? {
        val context = Faraday.getCurrentActivity() ?: return null

        val isFlutterRoute = options?.get("flutter") == true

        if (isFlutterRoute) {
            // singleTask 模式
            val builder = FaradayActivity.builder(name, arguments)

            // 你看到的绿色的闪屏就是这个
            builder.backgroundColor = Color.WHITE
            builder.activityClass = SingleTaskFlutterActivity::class.java

            return builder.build(context);
        }

        when (name) {
            "flutter2native" -> {
                return Intent(context, FlutterToNativeActivity::class.java)
            }
            "native2flutter" -> {
                return Intent(context, Native2FlutterActivity::class.java)
            }
            "tabContainer" -> {
                return Intent(context, TabContainerActivity::class.java)
            }
            else -> {
                val intent = Intent(Intent.ACTION_VIEW)
                intent.data = Uri.parse(name)
                intent.putExtra(KEY_ARGS, arguments)
                return intent
            }
        }

    }

    override fun pop(result: Serializable?) {
        val activity = Faraday.getCurrentActivity() ?: return
        if (result != null) {
            activity.setResult(Activity.RESULT_OK, Intent().apply { putExtra(KEY_ARGS, result) })
        }
        activity.finish()
    }

    override fun enableSwipeBack(enable: Boolean) {

    }

}

// 0x01 在 Application 的onCreate方法中启动FlutterEngine
if (!Faraday.startFlutterEngine(this, SimpleFlutterNavigator())) {
    GeneratedPluginRegistrant.registerWith(Faraday.engine)
}

// 0x02 打开一个Flutter页面
val intent = FaradayActivity.build(context, routeName, params)
context.startActivity(intent)

faraday 全家桶 (推荐)

在进行Flutter混合开发时会遇到很多相似的问题,我们提供了相应的解决方案大家玩的开心。

FAQ

是否支持使用第三方路由框架?

支持。

example中提供了flurogetx的实现范例

是否支持使用url配置路由?

支持。

可以保证3端统一使用url进行路由管理。

打包时提示 failed to load module 'g_faraday'

请使用xcode 12.3及以上版本

Communication

扫码加入微信群,请备注 faraday

wechat group

Contributing

If you wish to contribute a change to any of the existing plugins in this repo, please review our contribution guide and open a pull request.

License

g_faraday is released under the MIT license. See LICENSE for details.