fusion 1.0.0 copy "fusion: ^1.0.0" to clipboard
fusion: ^1.0.0 copied to clipboard

outdated

A Flutter plugin that manages hybrid stack on Android and iOS.

Fusion #

pub package

简介 #

Fusion 是新一代的混合管理框架,用于 Flutter 与 Native 页面统一管理,并支持页面通信、页面生命周期监听等功能。

Fusion 使用了 Flutter 新的导航框架 Navigator2.0,这使得 Fusion 可以更加灵活对 Flutter 路由栈进行管理。此外 Fusion 基于 FlutterEngineGroup 实现多 Engine,通过 FlutterEngineGroup 来创建新的 Engine,Flutter 官方宣称内存损耗仅占 180K,其本质是使 Engine 可以共享 GPU 上下文、字形和 isolate group snapshot,从而实现了更快的初始速度和更低的内存占用。这样在保证了性能的前提下混合栈的管理也变得更加便捷。

不像其他类似框架,随着 Flutter 版本的更新往往需要对框架本身进行版本适配工作,如果开发者维护不及时就会导致整个项目都无法使用新版 Flutter, Fusion 未对 Flutter Framework 层进行 Hook,较好的兼容性使得使用者可以更加从容地升级 Flutter。

设计严格遵循以下原则:

  • 轻量化
  • 最小侵入
  • 三端一致API

开始使用 #

0、在开始前需要按照 Flutter 官方文档,将 Flutter Module 项目接入到 Android 和 iOS 工程中。

1、初始化

Flutter 侧

使用 FusionApp 替换之前使用的 App Widget,并传入自定义的路由表

void main() {
  runApp(FusionApp(
    routeMap,
  ));
}

// 路由表
final Map<String, PageFactory> routeMap = {
  '/test': (arguments) => TestPage(arguments: arguments),
  '/404': (arguments) => UnknownPage(arguments: arguments),
};

Android 侧

在 Application 中进行初始化,并实现 FusionRouteDelegate 接口

class MyApplication : Application(), FusionRouteDelegate {

    override fun onCreate() {
        super.onCreate()
        Fusion.install(this, this)
    }

    override fun pushNativeRoute(name: String?, arguments: Map<String, Any>?) {
        // Flutter 跳转 Native 页面时被调用
      	// 根据路由 name 跳转对应原生 Activity
    }

    override fun pushFlutterRoute(name: String?, arguments: Map<String, Any>?) {
        // Native 跳转 Flutter 页面时被调用
      	// 根据路由 name 跳转对应 FusionActivity 或其子类
      	context?.let {
        	it.startActivity(buildFusionIntent(it, CustomFusionActivity::class.java, name, arguments))
        }
    }
}

iOS 侧

在 AppDelegate 中进行初始化,并实现 FusionRouteDelegate 代理

@UIApplicationMain
@objc class AppDelegate: UIResponder, UIApplicationDelegate, FusionRouteDelegate {
    
    func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      ...
      Fusion.instance.install(delegate: self)
      ...
    return true
  }
    
    func pushNativeRoute(name: String?, arguments: Dictionary<String, Any>?) {
        // Flutter 跳转 Native 页面时被调用
      	// 根据路由 name 跳转对应原生 VC
    }
    
    func pushFlutterRoute(name: String?, arguments: Dictionary<String, Any>?) {
        // Native 跳转 Flutter 页面时被调用
      	// 根据路由 name 跳转对应 FusionViewController 或其子类
        guard let name = name else {
            return
        }
        let navController = self.window?.rootViewController as? UINavigationController
        let fusionVc = CustomViewController(routeName: name, routeArguments: arguments)
        GeneratedPluginRegistrant.register(with: fusionVc.engine!)
        navController?.pushViewController(fusionVc, animated: true)
    }
}

2、Flutter 容器选择

Android 侧

多数情况下,应当直接使用 FusionActivty,除非存在 Flutter 页面和 Native 页面同时作为子页面存在,比如通过顶部或底部 Tab 切换的场景,这时就需要用到 FusionFragment。另外与其他类似框架相比,Fusion 可支持多 FusionFragment。

启动 FusionActivty(或其子类)时需要使用 Fusion 提供的 buildFusionIntent 方法,创建 FusionFragment 对象需要使用 FusionFragment.buildFragment 方法。

iOS侧

iOS中只有一种容器,即 FusionViewController,可以直接使用,也可通过继承其创建新的 ViewController。

3、路由API(FusionNavigator)

✅ push:指定页入栈,支持获取返回值

✅ pop:栈顶页出栈,支持设置返回值

TODO

❎ popUtil

❎ remove

❎ repalce

4、Flutter Plugin 注册

如果 Flutter Module 中依赖了 Flutter Plugin,需要按照以下步骤进行注册。

Android 侧

在 AndroidManifest.xml 加入以下代码,Flutter 框架会自动注册插件

<manifest>
    ...
    <application>
        ...
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

iOS 侧

每次创建 FusionViewContoller 对象都要通过以下代码注册

let fusionVc = FusionViewController(routeName: name, routeArguments: arguments)
GeneratedPluginRegistrant.register(with: fusionVc.engine!)

5、自定义 Channel

如果需要 Native 与 Flutter 进行通信,则需要自行创建 Channel,创建 Channel 方式如下(以 MethodChannel 为例):

Android 侧

①、如果使用的是 FusionFragment 容器,则需在对应的 Activity 类上实现 FusionMessengerProvider 接口,在接口方法中创建 Channel

class MyActivity : FragmentActivity(), FusionMessengerProvider {
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        //加载 FusionFragment
    }
  
    override fun configureFlutterChannel(binaryMessenger: BinaryMessenger) {
        val channel = MethodChannel(binaryMessenger, "自定义的channel名")
        channel.setMethodCallHandler { call, result -> 
            
        }
    }
}

②、如果使用的是 FusionActivity 容器,则需要创建一个新的 Activity 并继承 FusionActivity 并实现 FusionMessengerProvider 接口,在接口方法中创建 Channel

class CustomActivity : FusionActivity(), FusionMessengerProvider {
  
    override fun configureFlutterChannel(binaryMessenger: BinaryMessenger) {
        val channel = MethodChannel(binaryMessenger, "自定义的channel名")
        channel.setMethodCallHandler { call, result -> 
            
        }
    }
}

iOS 侧

①、如果直接使用了 FusionViewController 作为 Flutter 容器

let fusionVc = FusionViewController(routeName: name, routeArguments: arguments)
let channel = FlutterMethodChannel(name: "自定义的channel名", binaryMessenger: fusionVc.binaryMessenger)
        channel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
   				//根据call.method匹配路由
        }

②、如果创建一个继承自 FusionViewController 的 ViewController 作为 Flutter 容器

既可以按照①中的方式创建channel,也可以实现 FusionMessengerProvider 协议,在协议方法中创建 Channel

class CustomViewController : FusionViewController, FusionMessengerProvider {
    func configureFlutterChannel(binaryMessenger: FlutterBinaryMessenger) {
        let channel = FlutterMethodChannel(name: "自定义的channel名", binaryMessenger: binaryMessenger)
        channel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
   				//根据call.method匹配路由
        }
    }
}

BasicMessageChannel 和 EventChannel 使用也是类似。另外务必确保 Flutter 和 Native 使用的 Channel类型统一。

需要注意的是,自行创建的 Channel,Android 需要在 Activity 的 onDestroy、iOS 需要在 ViewController 的析构函数中对其置空,避免可能的内存泄漏。

Android 侧

override fun onDestroy() {
  super.onDestroy()
  channel?.setMethodCallHandler(null)
  channle = null
}

iOS 侧

deinit {
  channel?.setMethodCallHandler(nil)
  channel = nil
}
17
likes
0
points
156
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin that manages hybrid stack on Android and iOS.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on fusion