Flutter跨平台导航与页面跳转插件flutter_thrio的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter跨平台导航与页面跳转插件flutter_thrio的使用

thrio logo

pub package license

中文文档 英文文档 问题集
原仓库不再维护,代码已经很老了

最近版本更新会很快,主要是增加新特性,涉及到混合栈的稳定性的问题应该不多,可放心升级,发现问题加 QQ 群号码:1014085473,我会尽快解决。

注意: 不打算好好看看源码的使用者可以放弃这个库了,因为很多设定是比较死的,而我本人不打算花时间写太多文档

优势

  1. 稳定性、通用性在部分项目中得到验证,有用户反馈,将整个 app 的路由方案全部切换到后,崩溃率降低显著
  2. 内存占用方面,thrio 在连续打开 Flutter 页面的内存占用方面从一开始就碾压主流的 Flutter 混合栈,更进一步的,避开原理层面带来的内存优势,这里有个对比,也说明 thrio 在内存占用上的优异表现,传送门
  3. 支持 FlutterEngine 的复用,还支持 FlutterViewControllerFlutterActivity 的复用,这保证了 Flutter 混合栈框架在内存占用上是最优解
  4. 在 3 情形下,支持 跨栈路由 的能力,这是目前唯一能做到的 Flutter混合栈开源框架
  5. 在 3 情形下,除了提供 pushpop,也提供了 removepopTo 的能力,目前唯一能做到的 Flutter混合栈开源框架
  6. 在 3 情形下,提供页面通知的能力,组合 pushpop 的路由传参能力,可以让状态参数在页面间传递,省去很多 channel 通讯的必要
  7. 在 3 情形下,页面传参支持Json对象类型,单引擎下纯 Flutter 开发支持直接传递对象类型
  8. 在 3 情形下,支持完整的页面生命周期
  9. 在 3 情形下,支持完整的路由周期,兼容使用 FlutterNavigator 来打开对话框等弹窗
  10. 在 3 情形下,支持多引擎模式,可以在一个原生 App 中运行多份 Flutter 代码,目前唯一能做到的 Flutter 混合栈开源框架
  11. 在 3 情形下,解决 iOS 和 Android 上的侧滑返回手势冲突
  12. iOS 上自动隐藏 Flutter 页面的导航栏
  13. 额外的支持三端统一的模块化方式,更好的与路由API配合

劣势

  1. 在 iOS 上不支持 present,技术上完全可以实现,甚至使用者可以通过传参的方式在 builder 中自己 present,但为了 API 设计上统一,作者选择不支持 present,demo 中其实是有 present 的示例的,建议 present 的时候外套一个 UINavigationController,可以保证不管何时 push 时 API 都是有效的,flutter_thrio 是支持多 UINavigationController 的,有一点需要注意的是,如果多个 UINavigationController 内嵌于 UITabBar 中时,要注意无法同时将多个 FlutterViewController 呈现,不支持是因为支持的话无法进行引擎复用。
  2. 在 Android 上不支持 Fragment,原因是复杂性无法解决,作者目前不能够保证提供一个通用稳定的版本。

入门

  1. clone thrio 的源码,查看 demo,并运行起来
  2. 通过 pub 引入 thrio,建议采用 1.0.0 之后的版本,之前的版本支持1.22.x之前的Flutter SDK,但不建议继续采用这些老版本的 SDK,还是尽快升级到新版
  3. 模仿 thrio demo 中的源码,在现有工程上加入相关代码
  4. 不要继承 Flutter SDK 中的一些类,比如 FlutterViewControllerFlutterActivityFlutterAppDelegate
  5. 不要调用 GeneratedPluginRegistrantregisterWithRegistry 方法了,因为框架会自动调用
  6. url 至少保持两段

最后

  • 技术没有好与不好,使用在适合的场景才是最好的。
  • Flutter 在 客户端的适用场景会越来越广,个人比较看好。
  • 目前在移动端,一个好的 Flutter 混合栈框架是必须的,让你可以在大多数的页面上采用 Flutter 来开发从而达到提效的目的,少数涉及到 Flutter 不能很好支持的页面上继续使用原生开发,从而规避的 Flutter 的坑。
  • 如果所开发的是一个全新的 App,以后也不会涉及到老的代码的复用,或者不会涉及到 Flutter 支持不够良好的一些技术上的坑,确实可以考虑纯 Flutter。
  • 但上述情形极少,所以大部分的 Flutter 在引入的时候,都应该考虑以 Flutter 混合栈的方式进行,坑不是用来踩的,而是绕道而过。

示例代码

import 'dart:async';

import 'package:flutter_thrio/flutter_thrio.dart';

import 'src/app.dart' as app;

Future<void> main() async {
  ThrioLogger.v('main');
  runZonedGuarded(app.main, (error, stack) {
    Zone.current.handleUncaughtError(error, stack);
  });
}

@pragma('vm:entry-point')
Future<void> biz1() async {
  runZonedGuarded(app.biz1, (error, stack) {
    Zone.current.handleUncaughtError(error, stack);
  });
}

@pragma('vm:entry-point')
Future<void> biz2() async {
  runZonedGuarded(app.biz2, (error, stack) {
    Zone.current.handleUncaughtError(error, stack);
  });
}

完整的示例Demo

下面是一个完整的示例 Demo,展示了如何使用 flutter_thrio 进行页面导航和跳转。此示例包括两个页面:HomePageSecondPage

1. 添加依赖

pubspec.yaml 文件中添加 flutter_thrio 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_thrio: ^latest_version # 替换为最新版本号

2. 创建主页面 HomePage

import 'package:flutter/material.dart';
import 'package:flutter_thrio/flutter_thrio.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            ThrioRouter.push('/second_page', arguments: {'message': 'Hello from Home Page'});
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

3. 创建第二个页面 SecondPage

import 'package:flutter/material.dart';
import 'package:flutter_thrio/flutter_thrio.dart';

class SecondPage extends StatelessWidget {
  final Map<String, dynamic>? arguments;

  SecondPage({this.arguments});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Received message: ${arguments?['message'] ?? 'No message'}'),
            ElevatedButton(
              onPressed: () {
                ThrioRouter.pop({'response': 'Response from Second Page'});
              },
              child: Text('Back to Home Page'),
            ),
          ],
        ),
      ),
    );
  }
}

4. 配置路由

main.dart 中配置路由:

import 'package:flutter/material.dart';
import 'package:flutter_thrio/flutter_thrio.dart';
import 'home_page.dart';
import 'second_page.dart';

void main() {
  ThrioRouter.config(
    routes: {
      '/': (settings) => MaterialPageRoute(builder: (_) => HomePage()),
      '/second_page': (settings) => MaterialPageRoute(
        builder: (_) => SecondPage(arguments: settings.arguments),
      ),
    },
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Thrio Demo',
      home: ThrioRouter.root(),
    );
  }
}

通过以上步骤,您可以创建一个简单的应用来演示 flutter_thrio 的基本功能。希望这对您有所帮助!如果有任何问题,请随时提问。


更多关于Flutter跨平台导航与页面跳转插件flutter_thrio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter跨平台导航与页面跳转插件flutter_thrio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter开发中,flutter_thrio 是一个强大的跨平台导航与页面跳转插件,它允许你在Flutter应用中嵌入原生页面,并且可以在原生页面和Flutter页面之间自由跳转。下面是一个关于如何使用 flutter_thrio 的代码示例,包括如何在Flutter和原生页面之间进行导航和跳转。

1. 安装 flutter_thrio

首先,你需要在 pubspec.yaml 文件中添加 flutter_thrio 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_thrio: ^latest_version  # 请替换为最新版本号

然后运行 flutter pub get 来获取依赖。

2. 配置原生项目

iOS 配置

ios/Runner/AppDelegate.swift 中,你需要配置 ThrioEngine 并设置 windowrootViewControllerThrioNavigator

import UIKit
import Flutter
import flutter_thrio

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    
    let engine = FlutterEngine(name: "my_engine_id", project: nil)
    let navigator = ThrioNavigator(engine: engine, window: self.window!)
    self.window?.rootViewController = navigator
    
    // 配置ThrioEngine
    ThrioEngine.shared = ThrioEngine(engine: engine, navigator: navigator)
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Android 配置

android/app/src/main/kotlin/com/yourapp/MainActivity.kt 中,你需要配置 ThrioEngine 并设置 MainActivityThrioActivity

package com.yourapp

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
import com.thrio.flutter.thrio.ThrioEngine
import com.thrio.flutter.thrio.ThrioNavigator

class MainActivity: ThrioActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        // 配置ThrioEngine
        val navigator = ThrioNavigator(flutterEngine, this)
        ThrioEngine.shared = ThrioEngine(flutterEngine, navigator)
    }
}

3. 使用 flutter_thrio 进行导航

在Flutter代码中,你可以使用 Thrio.navigator 来跳转到原生页面或者Flutter页面。以下是一个简单的示例:

import 'package:flutter/material.dart';
import 'package:flutter_thrio/flutter_thrio.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Thrio Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Open Native Page'),
            ElevatedButton(
              onPressed: () {
                // 跳转到原生页面
                Thrio.navigator.pushNativePage(
                  url: 'native_page://example',
                  params: {
                    'key': 'value',
                  },
                );
              },
              child: Text('Go to Native Page'),
            ),
            SizedBox(height: 20),
            Text('Open Flutter Page'),
            ElevatedButton(
              onPressed: () {
                // 跳转到Flutter页面
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => FlutterPage()),
                );
              },
              child: Text('Go to Flutter Page'),
            ),
          ],
        ),
      ),
    );
  }
}

class FlutterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Page'),
      ),
      body: Center(
        child: Text('This is a Flutter page'),
      ),
    );
  }
}

4. 在原生页面中接收参数并返回结果

在原生代码中,你需要处理 flutter_thrio 传递的参数,并可以返回结果给Flutter。以下是一个简单的iOS示例:

import UIKit
import flutter_thrio

class NativePageViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 获取传递的参数
        if let params = ThrioEngine.shared?.currentParams {
            if let value = params["key"] as? String {
                print("Received parameter: \(value)")
            }
        }
        
        // 设置按钮点击事件返回结果给Flutter
        let button = UIButton(type: .system)
        button.setTitle("Return to Flutter", for: .normal)
        button.addTarget(self, action: #selector(returnToFlutter), for: .touchUpInside)
        self.view.addSubview(button)
        
        // 设置按钮的布局
        button.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
        ])
    }
    
    @objc func returnToFlutter() {
        // 返回结果给Flutter
        let result = ["result": "success"]
        ThrioEngine.shared?.popWithResult(result)
    }
}

在Android中,你需要类似地处理参数和返回结果。

以上代码示例展示了如何在Flutter和原生页面之间进行导航和参数传递。请注意,实际项目中可能需要根据具体需求进行更多的配置和调整。

回到顶部