Flutter 原生路由跳转行为插件g_faraday的使用
Flutter 插件g_faraday的使用
g_faraday
是一个用于Flutter混合栈开发的解决方案,支持iOS、Android和Flutter三端的所有原生路由跳转行为,并提供了丰富的特性如页面间回调传值、自定义页面切换动画等。本文将详细介绍如何使用 g_faraday
插件。
特性
- 支持iOS、Android、Flutter三端所有原生路由(页面切换)跳转行为
- 支持混合栈(native -> flutter -> native)路由跳转(popTo、replace …)
- 支持flutter页面作为root页面
- 支持flutter作为子页面加入原生堆栈
- 支持flutter作为弹出页面(背景透明到native层)
- 页面间回调传值完整支持
- iOS导航条自动隐藏/显示
WillPopScope
拦截滑动返回(iOS)或者返回按键键(Android)- 发送/接收全局通知
- 支持自定义页面切换动画
- 支持完整的生命周期监听
快速开始
添加依赖
在你的 pubspec.yaml
文件中添加 g_faraday
依赖:
dependencies:
g_faraday: ^0.7.0
Flutter端集成
在Flutter侧,主要是注册需要从原生打开的页面:
import 'package:flutter/cupertino.dart';
import 'package:g_faraday/g_faraday.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
// 定义 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'));
default:
return CupertinoPageRoute(builder: (context) => Text(settings.name));
}
});
// 将 route 赋给你的app widget
return CupertinoApp(
onGenerateRoute: (_) => route,
);
}
}
注意:不管是 CupertinoApp
还是 MaterialApp
都不要设置 home
。
iOS集成
为了实现从Flutter端打开原生页面的应用场景,我们需要实现一个打开原生页面的protocol:
import UIKit
import g_faraday
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)
}
}
// 在 `application: didFinishLaunchingWithOptions` 中启动flutter engine
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Faraday.default.startFlutterEngine(navigatorDelegate: self)
return true
}
}
Android集成
为了实现从Flutter端打开原生页面的应用场景,我们需要实现一组打开原生页面的接口:
import android.content.Intent
import android.os.Bundle
import androidx.core.app.ActivityCompat
import com.gfaraday.Faraday
import com.gfaraday.FaradayActivity
import com.gfaraday.FaradayNavigator
import java.io.Serializable
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) {
}
}
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
if (!Faraday.startFlutterEngine(this, SimpleFlutterNavigator())) {
GeneratedPluginRegistrant.registerWith(Faraday.engine)
}
}
}
示例Demo
以下是一个简单的示例Demo,展示了如何使用 g_faraday
插件来实现Flutter与原生页面之间的跳转:
import 'package:flutter/cupertino.dart';
import 'package:g_faraday/g_faraday.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Map<String, RouteFactory> routes = {
'home': (settings) => CupertinoPageRoute(
builder: (context) => HomePage(settings.arguments), settings: settings),
'native2flutter': (settings) => CupertinoPageRoute(
builder: (context) => Native2FlutterPage(settings.arguments),
settings: settings),
'flutter2flutter': (settings) => CupertinoPageRoute(
builder: (context) => Flutter2Flutter(index: settings.toJson.index),
settings: settings),
'tab1': (settings) =>
CupertinoPageRoute(builder: (context) => TabPage(), settings: settings),
'transparent_flutter': (settings) => CupertinoPageRoute(
builder: (context) => TransparentPage(),
settings: settings,
)
};
[@override](/user/override)
Widget build(BuildContext context) {
final color = Color.fromARGB(255, 6, 210, 116);
final route = faraday.wrapper(
(settings) => routes[settings.name]?.call(settings),
errorPage: _buildErrorPage,
);
final cupertinoApp = CupertinoApp(
theme: CupertinoThemeData(primaryColor: color),
debugShowCheckedModeBanner: false,
onGenerateRoute: (_) => route,
);
return Directionality(
textDirection: TextDirection.ltr,
child: Banner(
location: BannerLocation.topEnd,
message: 'faraday',
color: color,
textStyle: TextStyle(
color: CupertinoColors.white,
fontSize: 12 * 0.85,
fontWeight: FontWeight.w900,
height: 1.0,
),
child: cupertinoApp,
),
);
}
///
/// 出错页面
///
Widget _buildErrorPage(BuildContext context) {
return GestureDetector(
onTap: () => faraday.refresh(), // 刷新
behavior: HitTestBehavior.opaque,
child: Container(
color: CupertinoColors.lightBackgroundGray,
padding: EdgeInsets.only(left: 15.0, right: 15.0),
alignment: Alignment.center,
child: Text.rich(
TextSpan(children: [
TextSpan(
text: '404',
style: TextStyle(
color: CupertinoColors.systemRed,
fontSize: 64.0,
fontWeight: FontWeight.bold,
),
),
TextSpan(
text: '\n出错了,点击刷新',
style: TextStyle(
fontSize: 16.0,
color: CupertinoColors.placeholderText,
),
),
]),
textAlign: TextAlign.center,
),
),
);
}
}
class HomePage extends StatelessWidget {
final dynamic arguments;
HomePage(this.arguments);
[@override](/user/override)
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Home Page'),
),
child: Center(
child: CupertinoButton(
child: Text('Go to Native Page'),
onPressed: () {
faraday.push('native2flutter', arguments: {'key': 'value'});
},
),
),
);
}
}
class Native2FlutterPage extends StatelessWidget {
final dynamic arguments;
Native2FlutterPage(this.arguments);
[@override](/user/override)
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Native to Flutter Page'),
),
child: Center(
child: Text('Arguments from Native: $arguments'),
),
);
}
}
更多关于Flutter 原生路由跳转行为插件g_faraday的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter 原生路由跳转行为插件g_faraday的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter开发中,g_faraday
插件可能不是一个广为人知的库,但从其命名推测,它可能与网络请求拦截、调试或类似功能相关。尽管没有官方的详细文档或广泛的使用案例,我们可以尝试探索其基本用法,假设它提供了类似网络请求拦截的功能。
由于g_faraday
在Flutter社区中可能不太常见,且没有具体的官方文档或示例代码,以下是一个假设性的示例,展示如何在Flutter项目中集成和使用一个假设的网络请求拦截器插件。请注意,这里的代码是基于假设的API和功能,实际使用时需要根据g_faraday
的真实API进行调整。
假设性示例代码
1. 添加依赖
首先,在pubspec.yaml
文件中添加g_faraday
依赖(注意:这里假设它已经在pub.dev上可用):
dependencies:
flutter:
sdk: flutter
g_faraday: ^x.y.z # 替换为实际版本号
然后运行flutter pub get
来安装依赖。
2. 初始化插件
在你的Flutter应用的入口文件(通常是main.dart
)中初始化g_faraday
插件:
import 'package:flutter/material.dart';
import 'package:g_faraday/g_faraday.dart'; // 假设的导入路径
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化g_faraday插件
Faraday faraday = Faraday();
// 设置请求拦截器(假设的API)
faraday.addInterceptor((RequestOptions options) async {
// 在这里可以修改请求选项,或者记录日志
print('Intercepted request: ${options.path}');
// 可以选择性地返回修改后的RequestOptions,或者抛出异常来阻止请求
return options;
});
// 设置响应拦截器(假设的API)
faraday.addResponseInterceptor((Response response, RequestOptions options) async {
// 在这里可以修改响应数据,或者记录日志
print('Intercepted response: ${response.statusCode} for ${options.path}');
// 可以选择性地返回修改后的Response,或者抛出异常来处理错误
return response;
});
// 配置全局HTTP客户端使用Faraday
// 假设Faraday提供了一个方法来设置全局客户端
faraday.configureGlobalHttpClient();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Faraday Demo'),
),
body: Center(
child: Text('Check console for intercepted requests and responses'),
),
),
);
}
}
3. 使用HTTP客户端
在你的应用中,你可以像平常一样使用HTTP客户端,但所有的请求和响应都会被g_faraday
拦截器处理:
import 'package:http/http.dart' as http;
// 假设在某个地方发送HTTP请求
void sendRequest() async {
try {
var response = await http.get(Uri.parse('https://api.example.com/data'));
print('Response data: ${response.body}');
} catch (e) {
print('Request failed: $e');
}
}
注意事项
- 上述代码是基于假设的API和功能编写的,实际使用时需要根据
g_faraday
的真实API进行调整。 - 如果
g_faraday
插件提供了不同的初始化或配置方法,请查阅其官方文档或源代码以获取准确的信息。 - 如果
g_faraday
不是一个真实存在的Flutter插件,或者其功能与上述假设不符,那么你可能需要寻找其他网络请求拦截或调试的Flutter插件,如dio
的拦截器功能等。
希望这个假设性的示例能够帮助你开始探索g_faraday
插件的使用。如果有任何具体的问题或需要进一步的帮助,请查阅该插件的官方文档或联系其维护者。