Commit fb8519f8 authored by justin's avatar justin

Merge branch 'master' into v1.12.13-hotfixes

# Conflicts:
#	example/lib/simple_page_widgets.dart
#	lib/container/container_coordinator.dart
parents 802756a1 eeebe1d6
...@@ -30,7 +30,7 @@ bool isTopContainer = FlutterBoost.BoostContainer.of(context).onstage ...@@ -30,7 +30,7 @@ bool isTopContainer = FlutterBoost.BoostContainer.of(context).onstage
回答:无障碍模式下目前Flutter Engine有bug,已经提交issue和PR给flutter啦。请参考这个issue:https://github.com/alibaba/flutter_boost/issues/488及其分析。提交给flutter的PR见这里:https://github.com/flutter/engine/pull/14155 回答:无障碍模式下目前Flutter Engine有bug,已经提交issue和PR给flutter啦。请参考这个issue:https://github.com/alibaba/flutter_boost/issues/488及其分析。提交给flutter的PR见这里:https://github.com/flutter/engine/pull/14155
### 5. 在ios模拟器下运行最新的flutter boost会闪退 ### 5. 在ios模拟器下运行最新的flutter boost会闪退
回答:如上面第4条所说的,最新的flutter engine在voice over下有bug,会导致crash。因为模拟器下flutter默认会将voice over模式打开,所以其实就是辅助模式,这触发上面的bug:“在ios中voice over打开,demo在点击交互会crash”。 回答:如上面第4条所说的,最新的flutter engine在voice over下有bug,会导致crash。因为模拟器下flutter默认会将voice over模式打开,所以其实就是辅助模式,这触发上面的bug:“在ios中voice over打开,demo在点击交互会crash”。
可参考Engine的代码注释: 可参考Engine的代码注释:
```c++ ```c++
#if TARGET_OS_SIMULATOR #if TARGET_OS_SIMULATOR
......
1、为何使用flutter_boost?
官方的集成方案有诸多弊病:
- 日志不能输出到原生端;
- 存在内存泄漏的问题,使用boost可以让内存稳定;
- native调用flutter,flutter调用native,通道的封装,使开发更加简便;
- 同时对于页面生命周期的管理,也梳理的比较整齐
2、集成流程IOS
在delegate中做flutter初始化的工作
```
在appDelegate中引入,PlatformRouterImp,用于实现平台侧的页面打开和关闭,不建议直接使用用于页面打开,建议使用FlutterBoostPlugin中的open和close方法来打开或关闭页面;
PlatformRouterImp内部实现打开各种native页面的映射。
self.router = [PlatformRouterImp new];
//初始化FlutterBoost混合栈环境。应在程序使用混合栈之前调用。如在AppDelegate中。本函数默认需要flutter boost来注册所有插件。
[FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:self.router
onStart:^(FlutterEngine *engine) {
}];
```
PlatformRouterImp,内部实现打开native页面的路由代码截图
```
- (void)open:(NSString *)name
urlParams:(NSDictionary *)params
exts:(NSDictionary *)exts
completion:(void (^)(BOOL))completion
{
if ([name isEqualToString:@"page1"]) {//打开页面1
// 打开页面1的vc
return;
}
BOOL animated = [exts[@"animated"] boolValue];
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[self.navigationController pushViewController:vc animated:animated];
if(completion) completion(YES);
}
```
如何打开,关闭flutter页面,直接调用FlutterBoostPlugin的类方法即可。
```
/**
* 关闭页面,混合栈推荐使用的用于操作页面的接口
*
* @param uniqueId 关闭的页面唯一ID符
* @param resultData 页面要返回的结果(给上一个页面),会作为页面返回函数的回调参数
* @param exts 额外参数
* @param completion 关闭页面的即时回调,页面一旦关闭即回调
*/
+ (void)close:(NSString *)uniqueId
result:(NSDictionary *)resultData
exts:(NSDictionary *)exts
completion:(void (^)(BOOL))completion;
/**
* 打开新页面(默认以push方式),混合栈推荐使用的用于操作页面的接口;通过urlParams可以设置为以present方式打开页面:urlParams:@{@"present":@(YES)}
*
* @param url 打开的页面资源定位符
* @param urlParams 传人页面的参数; 若有特殊逻辑,可以通过这个参数设置回调的id
* @param exts 额外参数
* @param resultCallback 当页面结束返回时执行的回调,通过这个回调可以取得页面的返回数据,如close函数传入的resultData
* @param completion 打开页面的即时回调,页面一旦打开即回调
*/
+ (void)open:(NSString *)url
urlParams:(NSDictionary *)urlParams
exts:(NSDictionary *)exts
onPageFinished:(void (^)(NSDictionary *))resultCallback
completion:(void (^)(BOOL))completion;
/**
* Present方式打开新页面,混合栈推荐使用的用于操作页面的接口
*
* @param url 打开的页面资源定位符
* @param urlParams 传人页面的参数; 若有特殊逻辑,可以通过这个参数设置回调的id
* @param exts 额外参数
* @param resultCallback 当页面结束返回时执行的回调,通过这个回调可以取得页面的返回数据,如close函数传入的resultData
* @param completion 打开页面的即时回调,页面一旦打开即回调
*/
+ (void)present:(NSString *)url
urlParams:(NSDictionary *)urlParams
exts:(NSDictionary *)exts
onPageFinished:(void (^)(NSDictionary *))resultCallback
completion:(void (^)(BOOL))completion;
```
IOS如何传递数据给flutter
```
//name是事件的名称,arguments中是一个NSDictionary,OC代码
[FlutterBoostPlugin.sharedInstance sendEvent:@"name" arguments:@{}];
//flutter部分接收数据,dart代码
FlutterBoost.singleton.channel.addEventListener('name',
(name, arguments){
//todo
return;
});
```
flutter如何传递数据给native
```
//flutter代码,ChannelName是通道名称与native部分一致即可,tmp是map类型的参数
Map<String,dynamic> tmp = Map<String,dynamic>();
try{
FlutterBoost.singleton.channel.sendEvent(ChannelName, tmp);
}catch(e){
}
//IOS侧代码
[FlutterBoostPlugin.sharedInstance addEventListener:^(NSString *name, NSDictionary *arguments) {
} forName:@"statistic"];
```
flutter中页面的生命周期管理
```
enum ContainerLifeCycle {
Init,
Appear,//已经出现,很遗憾的是如果在native部分present页面,这里是不会回调的。
WillDisappear,
Disappear,
Destroy,
Background,
Foreground
}
FlutterBoost.singleton.addBoostContainerLifeCycleObserver(//这个类是单例,再每个页面的initState方法中添加即可监听
(ContainerLifeCycle state, BoostContainerSettings settings) {
//setttings是配置,name表示页面的名称,建议一定要等到当前页面Appear状态的时候再做操作,
print(
'FlutterBoost.singleton.addBoostContainerLifeCycleObserver '+state.toString()+' '+settings.name);
},
);
```
关于flutter部分打开新页面的回调的一些坑。
```
FlutterBoost.singleton
.open(CoursePage.routeName, urlParams: {
}).then((Map<dynamic, dynamic> value) {
print(
'call me when page is finished. did recieve second route result $value');
//这个方法会优先于addBoostContainerLifeCycleObserver中的appear方法调用,所以说有些方法在这里调用,如果appear还没有出现的话就会有问题。
});
```
3、集成流程Android(待补充)
\ No newline at end of file
...@@ -5,18 +5,19 @@ ...@@ -5,18 +5,19 @@
<b></b><br> <b></b><br>
<a href="README_CN.md">中文文档</a> <a href="README_CN.md">中文文档</a>
<a href="https://mp.weixin.qq.com/s?__biz=MzU4MDUxOTI5NA==&mid=2247484367&idx=1&sn=fcbc485f068dae5de9f68d52607ea08f&chksm=fd54d7deca235ec86249a9e3714ec18be8b2d6dc580cae19e4e5113533a6c5b44dfa5813c4c3&scene=0&subscene=131&clicktime=1551942425&ascene=7&devicetype=android-28&version=2700033b&nettype=ctnet&abtest_cookie=BAABAAoACwASABMABAAklx4AVpkeAMSZHgDWmR4AAAA%3D&lang=zh_CN&pass_ticket=1qvHqOsbLBHv3wwAcw577EHhNjg6EKXqTfnOiFbbbaw%3D&wx_header=1">中文介绍</a> <a href="https://mp.weixin.qq.com/s?__biz=MzU4MDUxOTI5NA==&mid=2247484367&idx=1&sn=fcbc485f068dae5de9f68d52607ea08f&chksm=fd54d7deca235ec86249a9e3714ec18be8b2d6dc580cae19e4e5113533a6c5b44dfa5813c4c3&scene=0&subscene=131&clicktime=1551942425&ascene=7&devicetype=android-28&version=2700033b&nettype=ctnet&abtest_cookie=BAABAAoACwASABMABAAklx4AVpkeAMSZHgDWmR4AAAA%3D&lang=zh_CN&pass_ticket=1qvHqOsbLBHv3wwAcw577EHhNjg6EKXqTfnOiFbbbaw%3D&wx_header=1">中文介绍</a>
<a href="INTEGRATION.md">集成相关</a>
</p> </p>
# Release Note # Release Note
Please checkout the release note for the latest 0.1.64 to see changes [0.1.64 release note](https://github.com/alibaba/flutter_boost/releases) Please checkout the release note for the latest 1.12.13+1 to see changes [1.12.13+1 release note](https://github.com/alibaba/flutter_boost/releases)
# FlutterBoost # FlutterBoost
A next-generation Flutter-Native hybrid solution. FlutterBoost is a Flutter plugin which enables hybrid integration of Flutter for your existing native apps with minimum efforts.The philosophy of FlutterBoost is to use Flutter as easy as using a WebView. Managing Native pages and Flutter pages at the same time is non-trivial in an existing App. FlutterBoost takes care of page resolution for you. The only thing you need to care about is the name of the page(usually could be an URL).  A next-generation Flutter-Native hybrid solution. FlutterBoost is a Flutter plugin which enables hybrid integration of Flutter for your existing native apps with minimum efforts.The philosophy of FlutterBoost is to use Flutter as easy as using a WebView. Managing Native pages and Flutter pages at the same time is non-trivial in an existing App. FlutterBoost takes care of page resolution for you. The only thing you need to care about is the name of the page(usually could be an URL). 
<a name="bf647454"></a> <a name="bf647454"></a>
# Prerequisites # Prerequisites
You need to add Flutter to your project before moving on.The version of the flutter SDK requires v1.9.1+hotfixes, or it will compile error. You need to add Flutter to your project before moving on.The version of the flutter SDK requires to match boost's version, or it will compile error.
...@@ -24,13 +25,8 @@ You need to add Flutter to your project before moving on.The version of the flut ...@@ -24,13 +25,8 @@ You need to add Flutter to your project before moving on.The version of the flut
| Flutter Boost Version | Support Flutter SDK Version | Description | Support AndroidX? | | Flutter Boost Version | Support Flutter SDK Version | Description | Support AndroidX? |
| --------------------- | --------------------------- | ------------------------------------------------------------ | ------------------ | | --------------------- | --------------------------- | ------------------------------------------------------------ | ------------------ |
| 0.1.50 | 1.5.4-hotfixes | android if other flutter versions or branches will compile incorrectly. | No |
| 0.1.51-0.1.59 | 1.5.4-hotfixes | bugfix for 0.1.50. | No |
| 0.1.60 | 1.9.1-hotfixes | Android does not support andriodx if other flutter branches will compile incorrectly. | No |
| 0.1.61-0.1.69 | 1.9.1-hotfixes | bugfix for 0.1.60. | No |
| 0.1.63 | 1.9.1-hotfixes | If other branches will compile incorrectly. Synchronize with the 0.1.60 code, and bugfix also merge to this branch. | No |
| 1.9.1+2 | 1.9.1-hotfixes | Rename the version number and start supporting androidx by default | Yes | | 1.9.1+2 | 1.9.1-hotfixes | Rename the version number and start supporting androidx by default | Yes |
| 1.12.13 | 1.12.13-hotfixes | supporting androidx | Yes | | 1.12.13+1 | 1.12.13-hotfixes | supporting androidx | Yes |
...@@ -39,10 +35,7 @@ You need to add Flutter to your project before moving on.The version of the flut ...@@ -39,10 +35,7 @@ You need to add Flutter to your project before moving on.The version of the flut
| Flutter Boost branch | Support Flutter SDK Version | Description | Support AndroidX? | | Flutter Boost branch | Support Flutter SDK Version | Description | Support AndroidX? |
| --------------------- | --------------------------- | ------------------------------------------------------------ | ------------------ | | --------------------- | --------------------------- | ------------------------------------------------------------ | ------------------ |
| v1.9.1-hotfixes | 1.9.1-hotfixes | for androidx | Yes | | v1.9.1-hotfixes | 1.9.1-hotfixes | for androidx | Yes |
| task/task_v1.9.1_support_hotfixes| 1.9.1-hotfixes | for support | NO |
| v1.12.13-hotfixes | 1.12.13-hotfixes | for androidx | Yes | | v1.12.13-hotfixes | 1.12.13-hotfixes | for androidx | Yes |
| task/task_v1.12.13_support_hotfixes| 1.12.13-hotfixes | for support | NO |
# Getting Started # Getting Started
...@@ -56,14 +49,7 @@ androidx branch ...@@ -56,14 +49,7 @@ androidx branch
flutter_boost: flutter_boost:
git: git:
url: 'https://github.com/alibaba/flutter_boost.git' url: 'https://github.com/alibaba/flutter_boost.git'
ref: ' 1.12.13' ref: '1.12.13+1'
```
support branch
```json
flutter_boost:
git:
url: 'https://github.com/alibaba/flutter_boost.git'
ref: 'task/task_v1.12.13_support_hotfixes'
``` ```
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# Release Note # Release Note
请查看最新版本0.1.64的release note 确认变更,[0.1.64 release note](https://github.com/alibaba/flutter_boost/releases) 请查看最新版本1.12.13+1的release note 确认变更,[1.12.13+1 release note](https://github.com/alibaba/flutter_boost/releases)
# FlutterBoost # FlutterBoost
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
# 前置条件 # 前置条件
在继续之前,您需要将Flutter集成到你现有的项目中。flutter sdk 的版本需要 v1.9.1-hotfixes,否则会编译失败. 在继续之前,您需要将Flutter集成到你现有的项目中。flutter sdk 的版本需要和boost版本适配,否则会编译失败.
# FAQ # FAQ
请阅读这篇文章: 请阅读这篇文章:
...@@ -24,25 +24,17 @@ ...@@ -24,25 +24,17 @@
| Flutter Boost 版本 | 支持的 Flutter SDK 版本 | Description | 是否支持 AndroidX? | | Flutter Boost 版本 | 支持的 Flutter SDK 版本 | Description | 是否支持 AndroidX? |
| ----------------------- | ----------------------- | ------------------------------------------------------------ | ------------------- | | ----------------------- | ----------------------- | ------------------------------------------------------------ | ------------------- |
| 0.1.50 | 1.5.4-hotfixes | android 如果其他 flutter 版本或者分支会编译错误。 | No |
| 0.1.51-0.1.59 | 1.5.4-hotfixes | 0.1.50 的 bugfix。 | No |
| 0.1.60 | 1.9.1-hotfixes | android 如果其他 flutter 分支会编译错误。 | No |
| 0.1.63 | 1.9.1-hotfixes | 和 0.1.60 代码同步, bugfix 也会合入该分支,如果其他分支会编译错误。 | No |
| 0.1.61-0.1.69 | 1.9.1-hotfixes | 0.1.60 的 bugfix。 | No |
| 1.9.1+2 | 1.9.1-hotfixes | 版本号重新命名,开始默认支持androidx | Yes | | 1.9.1+2 | 1.9.1-hotfixes | 版本号重新命名,开始默认支持androidx | Yes |
| 1.12.13 | 1.12.13 -hotfixes | 支持androidx | Yes | | 1.12.13+1 | 1.12.13 -hotfixes | 支持androidx | Yes |
| Flutter Boost 分支 | 支持的 Flutter SDK 版本 | Description | Support AndroidX? | | Flutter Boost 分支 | 支持的 Flutter SDK 版本 | Description | 是否支持 AndroidX? |
| --------------------- | --------------------------- | ------------------------------------------------------------ | ------------------ | | --------------------- | --------------------------- | ------------------------------------------------------------ | ------------------ |
| v1.9.1-hotfixes | 1.9.1-hotfixes | for androidx | Yes | | v1.9.1-hotfixes | 1.9.1-hotfixes | for androidx | Yes |
| task/task_v1.9.1_support_hotfixes| 1.9.1-hotfixes | for support | NO |
| v1.12.13-hotfixes | 1.12.13-hotfixes | for androidx | Yes | | v1.12.13-hotfixes | 1.12.13-hotfixes | for androidx | Yes |
| task/task_v1.12.13_support_hotfixes| 1.12.13-hotfixes | for support | NO |
# 安装 # 安装
...@@ -56,15 +48,7 @@ androidx branch ...@@ -56,15 +48,7 @@ androidx branch
flutter_boost: flutter_boost:
git: git:
url: 'https://github.com/alibaba/flutter_boost.git' url: 'https://github.com/alibaba/flutter_boost.git'
ref: '1.12.13' ref: '1.12.13+1'
```
support branch
```json
flutter_boost:
git:
url: 'https://github.com/alibaba/flutter_boost.git'
ref: 'task/task_v1.12.13_support_hotfixes'
``` ```
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
analyzer: analyzer:
strong-mode: strong-mode:
implicit-casts: false
implicit-dynamic: false implicit-dynamic: false
errors: errors:
# treat missing required parameters as a warning (not a hint) # treat missing required parameters as a warning (not a hint)
...@@ -38,9 +39,7 @@ analyzer: ...@@ -38,9 +39,7 @@ analyzer:
# see https://github.com/dart-lang/sdk/issues/28463 # see https://github.com/dart-lang/sdk/issues/28463
- "lib/i18n/messages_*.dart" - "lib/i18n/messages_*.dart"
- "lib/src/http/**" - "lib/src/http/**"
- "example/**"
- "example_swift/**"
- "test/**"
linter: linter:
rules: rules:
# these rules are documented on and in the same order as # these rules are documented on and in the same order as
...@@ -60,6 +59,7 @@ linter: ...@@ -60,6 +59,7 @@ linter:
- avoid_classes_with_only_static_members - avoid_classes_with_only_static_members
# - avoid_double_and_int_checks # only useful when targeting JS runtime # - avoid_double_and_int_checks # only useful when targeting JS runtime
- avoid_empty_else - avoid_empty_else
- avoid_equals_and_hash_code_on_mutable_classes
- avoid_field_initializers_in_const_classes - avoid_field_initializers_in_const_classes
- avoid_function_literals_in_foreach_calls - avoid_function_literals_in_foreach_calls
# - avoid_implementing_value_types # not yet tested # - avoid_implementing_value_types # not yet tested
...@@ -67,7 +67,9 @@ linter: ...@@ -67,7 +67,9 @@ linter:
# - avoid_js_rounded_ints # only useful when targeting JS runtime # - avoid_js_rounded_ints # only useful when targeting JS runtime
- avoid_null_checks_in_equality_operators - avoid_null_checks_in_equality_operators
# - avoid_positional_boolean_parameters # not yet tested # - avoid_positional_boolean_parameters # not yet tested
# - avoid_print # not yet tested
# - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
# - avoid_redundant_argument_values # not yet tested
- avoid_relative_lib_imports - avoid_relative_lib_imports
- avoid_renaming_method_parameters - avoid_renaming_method_parameters
- avoid_return_types_on_setters - avoid_return_types_on_setters
...@@ -77,13 +79,16 @@ linter: ...@@ -77,13 +79,16 @@ linter:
# - avoid_returning_this # there are plenty of valid reasons to return this # - avoid_returning_this # there are plenty of valid reasons to return this
# - avoid_setters_without_getters # not yet tested # - avoid_setters_without_getters # not yet tested
# - avoid_shadowing_type_parameters # not yet tested # - avoid_shadowing_type_parameters # not yet tested
# - avoid_single_cascade_in_expression_statements # not yet tested - avoid_single_cascade_in_expression_statements
- avoid_slow_async_io - avoid_slow_async_io
- avoid_types_as_parameter_names - avoid_types_as_parameter_names
# - avoid_types_on_closure_parameters # conflicts with always_specify_types # - avoid_types_on_closure_parameters # conflicts with always_specify_types
# - avoid_unnecessary_containers # not yet tested
- avoid_unused_constructor_parameters - avoid_unused_constructor_parameters
- avoid_void_async - avoid_void_async
# - avoid_web_libraries_in_flutter # not yet tested
- await_only_futures - await_only_futures
- camel_case_extensions
- camel_case_types - camel_case_types
- cancel_subscriptions - cancel_subscriptions
# - cascade_invocations # not yet tested # - cascade_invocations # not yet tested
...@@ -109,8 +114,11 @@ linter: ...@@ -109,8 +114,11 @@ linter:
# - lines_longer_than_80_chars # not yet tested # - lines_longer_than_80_chars # not yet tested
- list_remove_unrelated_type - list_remove_unrelated_type
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
# - missing_whitespace_between_adjacent_strings # not yet tested
- no_adjacent_strings_in_list - no_adjacent_strings_in_list
- no_duplicate_case_values - no_duplicate_case_values
# - no_logic_in_create_state # not yet tested
# - no_runtimeType_toString # not yet tested
- non_constant_identifier_names - non_constant_identifier_names
# - null_closures # not yet tested # - null_closures # not yet tested
# - omit_local_variable_types # opposite of always_specify_types # - omit_local_variable_types # opposite of always_specify_types
...@@ -136,9 +144,9 @@ linter: ...@@ -136,9 +144,9 @@ linter:
- prefer_equal_for_default_values - prefer_equal_for_default_values
# - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
- prefer_final_fields - prefer_final_fields
# - prefer_final_in_for_each # not yet tested - prefer_final_in_for_each
- prefer_final_locals - prefer_final_locals
# - prefer_for_elements_to_map_fromIterable # not yet tested - prefer_for_elements_to_map_fromIterable
- prefer_foreach - prefer_foreach
# - prefer_function_declarations_over_variables # not yet tested # - prefer_function_declarations_over_variables # not yet tested
- prefer_generic_function_type_aliases - prefer_generic_function_type_aliases
...@@ -150,9 +158,11 @@ linter: ...@@ -150,9 +158,11 @@ linter:
# - prefer_interpolation_to_compose_strings # not yet tested # - prefer_interpolation_to_compose_strings # not yet tested
- prefer_is_empty - prefer_is_empty
- prefer_is_not_empty - prefer_is_not_empty
- prefer_is_not_operator
- prefer_iterable_whereType - prefer_iterable_whereType
# - prefer_mixin # https://github.com/dart-lang/language/issues/32 # - prefer_mixin # https://github.com/dart-lang/language/issues/32
# - prefer_null_aware_operators # disable until NNBD, see https://github.com/flutter/flutter/pull/32711#issuecomment-492930932 # - prefer_null_aware_operators # disable until NNBD, see https://github.com/flutter/flutter/pull/32711#issuecomment-492930932
# - prefer_relative_imports # not yet tested
- prefer_single_quotes - prefer_single_quotes
- prefer_spread_collections - prefer_spread_collections
- prefer_typing_uninitialized_variables - prefer_typing_uninitialized_variables
...@@ -173,6 +183,7 @@ linter: ...@@ -173,6 +183,7 @@ linter:
# - unnecessary_await_in_return # not yet tested # - unnecessary_await_in_return # not yet tested
- unnecessary_brace_in_string_interps - unnecessary_brace_in_string_interps
- unnecessary_const - unnecessary_const
# - unnecessary_final # conflicts with prefer_final_locals
- unnecessary_getters_setters - unnecessary_getters_setters
# - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
- unnecessary_new - unnecessary_new
...@@ -181,14 +192,16 @@ linter: ...@@ -181,14 +192,16 @@ linter:
- unnecessary_overrides - unnecessary_overrides
- unnecessary_parenthesis - unnecessary_parenthesis
- unnecessary_statements - unnecessary_statements
# - unnecessary_string_interpolations
- unnecessary_this - unnecessary_this
- unrelated_type_equality_checks - unrelated_type_equality_checks
# - unsafe_html # not yet tested # - unsafe_html # not yet tested
- use_full_hex_values_for_flutter_colors - use_full_hex_values_for_flutter_colors
# - use_function_type_syntax_for_parameters # not yet tested # - use_function_type_syntax_for_parameters # not yet tested
# - use_key_in_widget_constructors # not yet tested
- use_rethrow_when_possible - use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested # - use_setters_to_change_properties # not yet tested
# - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
- valid_regexps - valid_regexps
# - void_checks # not yet tested - void_checks
\ No newline at end of file
...@@ -176,7 +176,7 @@ public class FlutterBoost { ...@@ -176,7 +176,7 @@ public class FlutterBoost {
} }
DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint( DartExecutor.DartEntrypoint entrypoint = new DartExecutor.DartEntrypoint(
FlutterMain.findAppBundlePath(), FlutterMain.findAppBundlePath(),
"main" mPlatform.dartEntrypoint()
); );
flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint); flutterEngine.getDartExecutor().executeDartEntrypoint(entrypoint);
...@@ -265,6 +265,9 @@ public class FlutterBoost { ...@@ -265,6 +265,9 @@ public class FlutterBoost {
return ConfigBuilder.this.isDebug; return ConfigBuilder.this.isDebug;
} }
@Override
public String dartEntrypoint() { return ConfigBuilder.this.dartEntrypoint; }
@Override @Override
public String initialRoute() { public String initialRoute() {
return ConfigBuilder.this.initialRoute; return ConfigBuilder.this.initialRoute;
......
...@@ -38,6 +38,8 @@ public abstract class Platform { ...@@ -38,6 +38,8 @@ public abstract class Platform {
public abstract boolean isDebug(); public abstract boolean isDebug();
public abstract String dartEntrypoint();
public abstract String initialRoute(); public abstract String initialRoute();
public FlutterBoost.BoostLifecycleListener lifecycleListener; public FlutterBoost.BoostLifecycleListener lifecycleListener;
......
...@@ -3,9 +3,11 @@ package com.taobao.idlefish.flutterboostexample; ...@@ -3,9 +3,11 @@ package com.taobao.idlefish.flutterboostexample;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.util.Log; import android.util.Log;
import com.idlefish.flutterboost.*; import com.idlefish.flutterboost.*;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.idlefish.flutterboost.interfaces.INativeRouter; import com.idlefish.flutterboost.interfaces.INativeRouter;
...@@ -13,7 +15,7 @@ import io.flutter.embedding.android.FlutterView; ...@@ -13,7 +15,7 @@ import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.GeneratedPluginRegistrant; import io.flutter.plugin.common.StandardMessageCodec;
public class MyApplication extends Application { public class MyApplication extends Application {
...@@ -41,6 +43,26 @@ public class MyApplication extends Application { ...@@ -41,6 +43,26 @@ public class MyApplication extends Application {
@Override @Override
public void onEngineCreated() { public void onEngineCreated() {
// 注册MethodChannel,监听flutter侧的getPlatformVersion调用
MethodChannel methodChannel = new MethodChannel(FlutterBoost.instance().engineProvider().getDartExecutor(), "flutter_native_channel");
methodChannel.setMethodCallHandler((call, result) -> {
if (call.method.equals("getPlatformVersion")) {
result.success(Build.VERSION.RELEASE);
} else {
result.notImplemented();
}
});
// 注册PlatformView viewTypeId要和flutter中的viewType对应
FlutterBoost
.instance()
.engineProvider()
.getPlatformViewsController()
.getRegistry()
.registerViewFactory("plugins.test/view", new TextPlatformViewFactory(StandardMessageCodec.INSTANCE));
} }
@Override @Override
......
package com.taobao.idlefish.flutterboostexample;
import io.flutter.app.FlutterPluginRegistry;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.StandardMessageCodec;
public class TextPlatformViewPlugin {
public static void register(PluginRegistry.Registrar registrar) {
registrar.platformViewRegistry().registerViewFactory("plugins.test/view",
new TextPlatformViewFactory(StandardMessageCodec.INSTANCE));
}
}
...@@ -24,6 +24,20 @@ ...@@ -24,6 +24,20 @@
[FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router [FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
onStart:^(FlutterEngine *engine) { onStart:^(FlutterEngine *engine) {
// 注册MethodChannel,监听flutter侧的getPlatformVersion调用
FlutterMethodChannel *flutterMethodChannel = [FlutterMethodChannel methodChannelWithName:@"flutter_native_channel" binaryMessenger:engine.binaryMessenger];
[flutterMethodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
NSString *method = call.method;
if ([method isEqualToString:@"getPlatformVersion"]) {
NSString *sysVersion = [[UIDevice currentDevice] systemVersion];
result(sysVersion);
} else {
result(FlutterMethodNotImplemented);
}
}];
}]; }];
self.window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds]; self.window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];
......
...@@ -16,20 +16,26 @@ class _MyAppState extends State<MyApp> { ...@@ -16,20 +16,26 @@ class _MyAppState extends State<MyApp> {
void initState() { void initState() {
super.initState(); super.initState();
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(<String, PageBuilder>{
'embeded': (pageName, params, _)=>EmbededFirstRouteWidget(), 'embeded': (String pageName, Map<String, dynamic> params, String _) =>
'first': (pageName, params, _) => FirstRouteWidget(), EmbeddedFirstRouteWidget(),
'firstFirst': (pageName, params, _) => FirstFirstRouteWidget(), 'first': (String pageName, Map<String, dynamic> params, String _) => FirstRouteWidget(),
'second': (pageName, params, _) => SecondRouteWidget(), 'firstFirst': (String pageName, Map<String, dynamic> params, String _) =>
'secondStateful': (pageName, params, _) => SecondStatefulRouteWidget(), FirstFirstRouteWidget(),
'tab': (pageName, params, _) => TabRouteWidget(), 'second': (String pageName, Map<String, dynamic> params, String _) => SecondRouteWidget(),
'platformView': (pageName, params, _) => PlatformRouteWidget(), 'secondStateful': (String pageName, Map<String, dynamic> params, String _) =>
'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params), SecondStatefulRouteWidget(),
'tab': (String pageName, Map<String, dynamic> params, String _) => TabRouteWidget(),
'platformView': (String pageName, Map<String, dynamic> params, String _) =>
PlatformRouteWidget(),
'flutterFragment': (String pageName, Map<String, dynamic> params, String _) =>
FragmentRouteWidget(params),
///可以在native层通过 getContainerParams 来传递参数 ///可以在native层通过 getContainerParams 来传递参数
'flutterPage': (pageName, params, _) { 'flutterPage': (String pageName, Map<String, dynamic> params, String _) {
print("flutterPage params:$params"); print('flutterPage params:$params');
return FlutterRouteWidget(params:params); return FlutterRouteWidget(params: params);
}, },
}); });
FlutterBoost.singleton.addBoostNavigatorObserver(TestBoostNavigatorObserver()); FlutterBoost.singleton.addBoostNavigatorObserver(TestBoostNavigatorObserver());
...@@ -40,31 +46,36 @@ class _MyAppState extends State<MyApp> { ...@@ -40,31 +46,36 @@ class _MyAppState extends State<MyApp> {
return MaterialApp( return MaterialApp(
title: 'Flutter Boost example', title: 'Flutter Boost example',
builder: FlutterBoost.init(postPush: _onRoutePushed), builder: FlutterBoost.init(postPush: _onRoutePushed),
home: Container( home: Container(color: Colors.white));
color:Colors.white
));
} }
void _onRoutePushed( void _onRoutePushed(
String pageName, String uniqueId, Map params, Route route, Future _) { String pageName,
} String uniqueId,
Map<String, dynamic> params,
Route<dynamic> route,
Future<dynamic> _,
) {}
} }
class TestBoostNavigatorObserver extends NavigatorObserver{
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didPush"); class TestBoostNavigatorObserver extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
print('flutterboost#didPush');
} }
@override
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) { void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didPop"); print('flutterboost#didPop');
} }
@override
void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) { void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didRemove"); print('flutterboost#didRemove');
} }
@override
void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) { void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
print("flutterboost#didReplace"); print('flutterboost#didReplace');
} }
} }
...@@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart'; ...@@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
typedef void TextViewCreatedCallback(TextViewController controller); typedef TextViewCreatedCallback = void Function(TextViewController controller);
class TextView extends StatefulWidget { class TextView extends StatefulWidget {
const TextView({ const TextView({
...@@ -34,13 +34,13 @@ class _TextViewState extends State<TextView> { ...@@ -34,13 +34,13 @@ class _TextViewState extends State<TextView> {
if (widget.onTextViewCreated == null) { if (widget.onTextViewCreated == null) {
return; return;
} }
widget.onTextViewCreated(new TextViewController._(id)); widget.onTextViewCreated(TextViewController._(id));
} }
} }
class TextViewController { class TextViewController {
TextViewController._(int id) TextViewController._(int id)
: _channel = new MethodChannel('plugins.felix.angelov/textview_$id'); : _channel = MethodChannel('plugins.felix.angelov/textview_$id');
final MethodChannel _channel; final MethodChannel _channel;
......
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_boost/flutter_boost.dart'; import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_boost_example/platform_view.dart'; import 'package:flutter_boost_example/platform_view.dart';
class FirstRouteWidget extends StatefulWidget { class FirstRouteWidget extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() => _FirstRouteWidgetState();
return new _FirstRouteWidgetState();
}
} }
class _FirstRouteWidgetState extends State<FirstRouteWidget>{
class _FirstRouteWidgetState extends State<FirstRouteWidget> {
_FirstRouteWidgetState(); _FirstRouteWidgetState();
// flutter 侧MethodChannel配置,channel name需要和native侧一致
static const MethodChannel _methodChannel = MethodChannel('flutter_native_channel');
String _systemVersion = '';
Future<dynamic> _getPlatformVersion() async {
try {
final String result = await _methodChannel.invokeMethod('getPlatformVersion');
print('getPlatformVersion:' + result);
setState(() {
_systemVersion = result;
});
} on PlatformException catch (e) {
print(e.message);
}
}
@override @override
void initState() { void initState() {
print('initState'); print('initState');
...@@ -45,80 +63,90 @@ class _FirstRouteWidgetState extends State<FirstRouteWidget>{ ...@@ -45,80 +63,90 @@ class _FirstRouteWidgetState extends State<FirstRouteWidget>{
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('First Route')),
title: Text('First Route'),
),
body: Center( body: Center(
child: child: Column(
Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: children: <Widget>[
<Widget>[
RaisedButton( RaisedButton(
child: Text('Open native page'), child: const Text('Open native page'),
onPressed: () { onPressed: () {
print("open natve page!"); print('open natve page!');
FlutterBoost.singleton.open("native").then((Map value) { FlutterBoost.singleton
.open('native')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve native route result $value"); 'call me when page is finished. did recieve native route result $value');
}); });
}, },
), ),
RaisedButton( RaisedButton(
child: Text('Open FF route'), child: const Text('Open FF route'),
onPressed: () { onPressed: () {
print("open FF page!"); print('open FF page!');
FlutterBoost.singleton.open("firstFirst").then((Map value) { FlutterBoost.singleton
.open('firstFirst')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve FF route result $value"); 'call me when page is finished. did recieve FF route result $value');
}); });
}, },
), ),
RaisedButton( RaisedButton(
child: Text('Open second route1'), child: const Text('Open second route1'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
RaisedButton( RaisedButton(
child: Text('Present second stateful route'), child: const Text('Present second stateful route'),
onPressed: () { onPressed: () {
print("Present second stateful page!"); print('Present second stateful page!');
FlutterBoost.singleton.open("secondStateful",urlParams:<dynamic,dynamic>{"present":true}).then((Map value) { FlutterBoost.singleton.open('secondStateful',
urlParams: <String, dynamic>{
'present': true
}).then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second stateful route result $value"); 'call me when page is finished. did recieve second stateful route result $value');
}); });
}, },
), ),
RaisedButton( RaisedButton(
child: Text('Present second route'), child: const Text('Present second route'),
onPressed: () { onPressed: () {
print("Present second page!"); print('Present second page!');
FlutterBoost.singleton.open("second",urlParams:<dynamic,dynamic>{"present":true}).then((Map value) { FlutterBoost.singleton.open('second',
urlParams: <String, dynamic>{
'present': true
}).then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
RaisedButton(
child: Text('Get system version by method channel:' + _systemVersion),
onPressed: () => _getPlatformVersion(),
),
], ],
), ),
), ),
); );
} }
} }
class FirstFirstRouteWidget extends StatefulWidget { class FirstFirstRouteWidget extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() => _FirstFirstRouteWidgetState();
return new _FirstFirstRouteWidgetState();
}
} }
class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget> {
_FirstFirstRouteWidgetState(); _FirstFirstRouteWidgetState();
@override @override
...@@ -154,20 +182,18 @@ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{ ...@@ -154,20 +182,18 @@ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('First Route')),
title: Text('First Route'),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: Text('Open first route'), child: const Text('Open first route'),
onPressed: () { onPressed: () {
print('open first page again!');
print("open first page again!"); FlutterBoost.singleton
FlutterBoost.singleton.open("first").then((Map value){ .open('first')
print("did recieve first route result"); .then((Map<dynamic, dynamic> value) {
print("did recieve first route result $value"); print('did recieve first route result');
print('did recieve first route result $value');
}); });
}, },
), ),
), ),
...@@ -175,34 +201,33 @@ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{ ...@@ -175,34 +201,33 @@ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{
} }
} }
class EmbededFirstRouteWidget extends StatefulWidget { class EmbeddedFirstRouteWidget extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() => _EmbeddedFirstRouteWidgetState();
// TODO: implement createState
return _EmbededFirstRouteWidgetState();
}
} }
class _EmbededFirstRouteWidgetState extends State<EmbededFirstRouteWidget> { class _EmbeddedFirstRouteWidgetState extends State<EmbeddedFirstRouteWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print('_EmbededFirstRouteWidgetState build called!'); print('_EmbededFirstRouteWidgetState build called!');
return Scaffold( return Scaffold(
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: Text('Open second route2'), child: const Text('Open second route2'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
), ),
); );
} }
@override @override
void dispose() { void dispose() {
print('[XDEBUG]:_EmbededFirstRouteWidgetState disposing~'); print('[XDEBUG]:_EmbededFirstRouteWidgetState disposing~');
...@@ -212,29 +237,24 @@ class _EmbededFirstRouteWidgetState extends State<EmbededFirstRouteWidget> { ...@@ -212,29 +237,24 @@ class _EmbededFirstRouteWidgetState extends State<EmbededFirstRouteWidget> {
class SecondStatefulRouteWidget extends StatefulWidget { class SecondStatefulRouteWidget extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() => _SecondStatefulRouteWidgetState();
// TODO: implement createState
return _SecondStatefulRouteWidgetState();
}
} }
class _SecondStatefulRouteWidgetState extends State<SecondStatefulRouteWidget>{
class _SecondStatefulRouteWidgetState extends State<SecondStatefulRouteWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('SecondStateful Route')),
title: Text("SecondStateful Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
// Navigate back to first route when tapped. // Navigate back to first route when tapped.
final BoostContainerSettings settings =
BoostContainerSettings settings =
BoostContainer.of(context).settings; BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId, FlutterBoost.singleton.close(settings.uniqueId,
result: <dynamic,dynamic>{"result": "data from second"}); result: <String, dynamic>{'result': 'data from second'});
}, },
child: Text('Go back with result!'), child: const Text('Go back with result!'),
), ),
), ),
); );
...@@ -251,20 +271,19 @@ class SecondRouteWidget extends StatelessWidget { ...@@ -251,20 +271,19 @@ class SecondRouteWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Second Route')),
title: Text("Second Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
// Navigate back to first route when tapped. // Navigate back to first route when tapped.
final BoostContainerSettings settings =
BoostContainerSettings settings =
BoostContainer.of(context).settings; BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId, FlutterBoost.singleton.close(
result: <dynamic,dynamic>{"result": "data from second"}); settings.uniqueId,
result: <String, dynamic>{'result': 'data from second'},
);
}, },
child: Text('Go back with result!'), child: const Text('Go back with result!'),
), ),
), ),
); );
...@@ -275,15 +294,13 @@ class TabRouteWidget extends StatelessWidget { ...@@ -275,15 +294,13 @@ class TabRouteWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Tab Route')),
title: Text("Tab Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
FlutterBoost.singleton.open("second"); FlutterBoost.singleton.open('second');
}, },
child: Text('Open second route3'), child: const Text('Open second route3'),
), ),
), ),
); );
...@@ -294,17 +311,17 @@ class PlatformRouteWidget extends StatelessWidget { ...@@ -294,17 +311,17 @@ class PlatformRouteWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Platform Route')),
title:Text("Platform Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: TextView(), child: const TextView(),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -312,9 +329,11 @@ class PlatformRouteWidget extends StatelessWidget { ...@@ -312,9 +329,11 @@ class PlatformRouteWidget extends StatelessWidget {
); );
} }
} }
class FlutterRouteWidget extends StatefulWidget { class FlutterRouteWidget extends StatefulWidget {
FlutterRouteWidget({this.params,this.message}); const FlutterRouteWidget({this.params, this.message});
final Map params;
final Map<String, dynamic> params;
final String message; final String message;
@override @override
...@@ -322,34 +341,50 @@ class FlutterRouteWidget extends StatefulWidget { ...@@ -322,34 +341,50 @@ class FlutterRouteWidget extends StatefulWidget {
} }
class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
final TextEditingController _usernameController = TextEditingController();
// flutter 侧MethodChannel配置,channel name需要和native侧一致
static const MethodChannel _methodChannel = MethodChannel('flutter_native_channel');
String _systemVersion = '';
Future<dynamic> _getPlatformVersion() async {
try {
final String result = await _methodChannel.invokeMethod('getPlatformVersion');
print('getPlatformVersion:' + result);
setState(() {
_systemVersion = result;
});
} on PlatformException catch (e) {
print(e.message);
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final String message=widget.message; final String message = widget.message;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
brightness:Brightness.light, brightness: Brightness.light,
backgroundColor: Colors.white, backgroundColor: Colors.white,
textTheme:new TextTheme(title: TextStyle(color: Colors.black)) , textTheme: const TextTheme(title: TextStyle(color: Colors.black)),
title: const Text('flutter_boost_example'),
title: Text('flutter_boost_example'),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
child:Container( child: Container(
margin: const EdgeInsets.all(24.0), margin: const EdgeInsets.all(24.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Container( Container(
margin: const EdgeInsets.only(top: 10.0,bottom: 20.0), margin: const EdgeInsets.only(top: 10.0, bottom: 20.0),
child: Text( child: Text(
message ?? "This is a flutter activity \n params:${widget.params}", message ??
'This is a flutter activity \n params:${widget.params}',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
), ),
// Expanded(child: Container()),
const CupertinoTextField( const CupertinoTextField(
prefix: Icon( prefix: Icon(
CupertinoIcons.person_solid, CupertinoIcons.person_solid,
...@@ -359,136 +394,148 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -359,136 +394,148 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 12.0), padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 12.0),
clearButtonMode: OverlayVisibilityMode.editing, clearButtonMode: OverlayVisibilityMode.editing,
textCapitalization: TextCapitalization.words, textCapitalization: TextCapitalization.words,
),
new TextField(
enabled: true,
autocorrect: true,
style: const TextStyle(
fontSize: 20.0,
color: const Color(0xFF222222),
fontWeight: FontWeight.w500),
), new TextField(
controller: new TextEditingController(),
focusNode:FocusNode(),
enabled: true,
autocorrect: false, autocorrect: false,
style: const TextStyle( decoration: BoxDecoration(
fontSize: 20.0, border: Border(
color: const Color(0xFF222222), bottom: BorderSide(
fontWeight: FontWeight.w500), width: 0.0, color: CupertinoColors.inactiveGray),
),
),
placeholder: 'Name',
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open native page', 'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb /// 例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("sample://nativePage", urlParams: <dynamic,dynamic>{ 'sample://nativePage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open first', 'open first',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb /// 例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("first", urlParams: <dynamic,dynamic>{ 'first',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open second', 'open second',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb /// 例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("second", urlParams:<dynamic,dynamic> { 'second',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open tab', 'open tab',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb /// 例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("tab", urlParams:<dynamic,dynamic> { 'tab',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open flutter page', 'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb /// 例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("sample://flutterPage", urlParams:<String,dynamic> { 'sample://flutterPage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'push flutter widget', 'push flutter widget',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () { onTap: () {
Navigator.push<dynamic>(context, Navigator.push<dynamic>(
MaterialPageRoute<dynamic>(builder: (_) => PushWidget())); context,
MaterialPageRoute<dynamic>(builder: (_) => PushWidget()),
);
}, },
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'push Platform demo', 'push Platform demo',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () { onTap: () {
Navigator.push<dynamic>(context, Navigator.push<dynamic>(
MaterialPageRoute<dynamic>(builder: (_) => PlatformRouteWidget())); context,
MaterialPageRoute<dynamic>(
builder: (_) => PlatformRouteWidget()),
);
}, },
), ),
InkWell( InkWell(
...@@ -496,16 +543,27 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -496,16 +543,27 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
),
),
onTap: () =>
FlutterBoost.singleton.open('sample://flutterFragmentPage'),
),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'get system version by method channel:' + _systemVersion,
style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => FlutterBoost.singleton onTap: () => _getPlatformVersion(),
.open("sample://flutterFragmentPage"),
), ),
], ],
), ),
), ),
), ),
); );
...@@ -513,23 +571,21 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -513,23 +571,21 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
} }
class FragmentRouteWidget extends StatelessWidget { class FragmentRouteWidget extends StatelessWidget {
final Map params; const FragmentRouteWidget(this.params);
FragmentRouteWidget(this.params); final Map<String, dynamic> params;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('flutter_boost_example')),
title: Text('flutter_boost_example'),
),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Container( Container(
margin: const EdgeInsets.only(top: 80.0), margin: const EdgeInsets.only(top: 80.0),
child: Text( child: Text(
"This is a flutter fragment", 'This is a flutter fragment',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -537,7 +593,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -537,7 +593,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 32.0), margin: const EdgeInsets.only(top: 32.0),
child: Text( child: Text(
params['tag'] ?? '', '${params['tag']}' ?? '',
style: TextStyle(fontSize: 28.0, color: Colors.red), style: TextStyle(fontSize: 28.0, color: Colors.red),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -548,34 +604,37 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -548,34 +604,37 @@ class FragmentRouteWidget extends StatelessWidget {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open native page', 'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton.open("sample://nativePage"), ),
onTap: () => FlutterBoost.singleton.open('sample://nativePage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open flutter page', 'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton.open("sample://flutterPage"), ),
onTap: () => FlutterBoost.singleton.open('sample://flutterPage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 80.0), margin: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 80.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () => onTap: () =>
FlutterBoost.singleton.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
) )
], ],
), ),
...@@ -591,15 +650,8 @@ class PushWidget extends StatefulWidget { ...@@ -591,15 +650,8 @@ class PushWidget extends StatefulWidget {
class _PushWidgetState extends State<PushWidget> { class _PushWidgetState extends State<PushWidget> {
VoidCallback _backPressedListenerUnsub; VoidCallback _backPressedListenerUnsub;
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override @override
void didChangeDependencies() { void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies(); super.didChangeDependencies();
// if (_backPressedListenerUnsub == null) { // if (_backPressedListenerUnsub == null) {
...@@ -615,7 +667,6 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -615,7 +667,6 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
void dispose() { void dispose() {
// TODO: implement dispose
print('[XDEBUG] - PushWidget is disposing~'); print('[XDEBUG] - PushWidget is disposing~');
super.dispose(); super.dispose();
_backPressedListenerUnsub?.call(); _backPressedListenerUnsub?.call();
...@@ -623,6 +674,6 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -623,6 +674,6 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FlutterRouteWidget(message: "Pushed Widget"); return const FlutterRouteWidget(message: 'Pushed Widget');
} }
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class TestPage extends StatefulWidget { class TestPage extends StatefulWidget {
TestPage({Key key, this.title = "Input Test"}) : super(key: key); const TestPage({
Key key,
this.title = 'Input Test',
}) : super(key: key);
final String title; final String title;
...@@ -18,24 +21,16 @@ class _TestPageState extends State<TestPage> { ...@@ -18,24 +21,16 @@ class _TestPageState extends State<TestPage> {
}); });
} }
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: Text(widget.title)),
title: Text(widget.title),
),
body: SafeArea( body: SafeArea(
bottom: false, bottom: false,
child: ListView( child: ListView(
children: <Widget>[ children: <Widget>[
Container( Container(
child: Text( child: const Text(
'You have pushed the button this many times:', 'You have pushed the button this many times:',
), ),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
...@@ -50,10 +45,7 @@ class _TestPageState extends State<TestPage> { ...@@ -50,10 +45,7 @@ class _TestPageState extends State<TestPage> {
alignment: Alignment.center, alignment: Alignment.center,
), ),
Container( Container(
child: TextField( child: const TextField(minLines: 2, maxLines: 10),
minLines: 2,
maxLines: 10,
),
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
), ),
TestTextField(), TestTextField(),
...@@ -98,15 +90,13 @@ class _TestPageState extends State<TestPage> { ...@@ -98,15 +90,13 @@ class _TestPageState extends State<TestPage> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
), ),
Container( Container(
child: TextField( child: const TextField(minLines: 2, maxLines: 10),
minLines: 2,
maxLines: 10,
),
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
), ),
TestTextField(), TestTextField(),
], ],
)), ),
),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter, onPressed: _incrementCounter,
tooltip: 'Increment', tooltip: 'Increment',
...@@ -123,22 +113,22 @@ class TestTextField extends StatefulWidget { ...@@ -123,22 +113,22 @@ class TestTextField extends StatefulWidget {
class _TestTextFieldState extends State<TestTextField> { class _TestTextFieldState extends State<TestTextField> {
FocusNode _node; FocusNode _node;
PersistentBottomSheetController _controller; PersistentBottomSheetController<dynamic> _controller;
@override @override
void initState() { void initState() {
// TODO: implement initState
super.initState(); super.initState();
_node = FocusNode(); _node = FocusNode();
_node.addListener(() { _node.addListener(() {
if (_node.hasFocus) { if (_node.hasFocus) {
print('showBottomSheet'); print('showBottomSheet');
_controller = Scaffold.of(context) _controller = Scaffold.of(context).showBottomSheet<dynamic>(
.showBottomSheet<dynamic>((BuildContext ctx) => Container( (BuildContext ctx) => Container(
width: double.infinity, width: double.infinity,
height: 36.0, height: 36.0,
color: Colors.deepPurple, color: Colors.deepPurple,
)); ),
);
} else { } else {
if (_controller != null) { if (_controller != null) {
//Navigator.of(context).pop(); //Navigator.of(context).pop();
......
...@@ -6,13 +6,12 @@ ...@@ -6,13 +6,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_boost_example/main.dart';
import '../lib/main.dart';
void main() { void main() {
testWidgets('Verify Platform version', (WidgetTester tester) async { testWidgets('Verify Platform version', (WidgetTester tester) async {
// Build our app and trigger a frame. // Build our app and trigger a frame.
await tester.pumpWidget(new MyApp()); await tester.pumpWidget(MyApp());
// Verify that platform version is retrieved. // Verify that platform version is retrieved.
expect( expect(
......
...@@ -16,17 +16,22 @@ class _MyAppState extends State<MyApp> { ...@@ -16,17 +16,22 @@ class _MyAppState extends State<MyApp> {
void initState() { void initState() {
super.initState(); super.initState();
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(<String, PageBuilder>{
'first': (pageName, params, _) => FirstRouteWidget(), 'first': (String pageName, Map<String, dynamic> params, String _) =>
'second': (pageName, params, _) => SecondRouteWidget(), FirstRouteWidget(),
'tab': (pageName, params, _) => TabRouteWidget(), 'second': (String pageName, Map<String, dynamic> params, String _) =>
'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params), SecondRouteWidget(),
'tab': (String pageName, Map<String, dynamic> params, String _) =>
TabRouteWidget(),
'flutterFragment':
(String pageName, Map<String, dynamic> params, String _) =>
FragmentRouteWidget(params),
///可以在native层通过 getContainerParams 来传递参数 ///可以在native层通过 getContainerParams 来传递参数
'flutterPage': (pageName, params, _) { 'flutterPage': (String pageName, Map<String, dynamic> params, String _) {
print("flutterPage params:$params"); print('flutterPage params:$params');
return FlutterRouteWidget(); return const FlutterRouteWidget();
}, },
}); });
} }
...@@ -36,10 +41,15 @@ class _MyAppState extends State<MyApp> { ...@@ -36,10 +41,15 @@ class _MyAppState extends State<MyApp> {
return MaterialApp( return MaterialApp(
title: 'Flutter Boost example', title: 'Flutter Boost example',
builder: FlutterBoost.init(postPush: _onRoutePushed), builder: FlutterBoost.init(postPush: _onRoutePushed),
home: Container()); home: Container(),
);
} }
void _onRoutePushed( void _onRoutePushed(
String pageName, String uniqueId, Map params, Route route, Future _) { String pageName,
} String uniqueId,
Map<String, dynamic> params,
Route<dynamic> route,
Future<dynamic> _,
) {}
} }
...@@ -6,15 +6,18 @@ class FirstRouteWidget extends StatelessWidget { ...@@ -6,15 +6,18 @@ class FirstRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('First Route'), title: const Text('First Route'),
), ),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: Text('Open second route'), child: const Text('Open second route'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
print("call me when page is finished. did recieve second route result $value"); .open('second')
.then((Map<dynamic, dynamic> value) {
print(
'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -28,19 +31,21 @@ class SecondRouteWidget extends StatelessWidget { ...@@ -28,19 +31,21 @@ class SecondRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text("Second Route"), title: const Text('Second Route'),
), ),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
// Navigate back to first route when tapped. // Navigate back to first route when tapped.
BoostContainerSettings settings = final BoostContainerSettings settings =
BoostContainer.of(context).settings; BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId, FlutterBoost.singleton.close(
result: <dynamic,dynamic>{"result": "data from second"}); settings.uniqueId,
result: <String, dynamic>{'result': 'data from second'},
);
}, },
child: Text('Go back with result!'), child: const Text('Go back with result!'),
), ),
), ),
); );
...@@ -51,15 +56,13 @@ class TabRouteWidget extends StatelessWidget { ...@@ -51,15 +56,13 @@ class TabRouteWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Tab Route')),
title: Text("Tab Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
FlutterBoost.singleton.open("second"); FlutterBoost.singleton.open('second');
}, },
child: Text('Open second route'), child: const Text('Open second route'),
), ),
), ),
); );
...@@ -67,15 +70,15 @@ class TabRouteWidget extends StatelessWidget { ...@@ -67,15 +70,15 @@ class TabRouteWidget extends StatelessWidget {
} }
class FlutterRouteWidget extends StatelessWidget { class FlutterRouteWidget extends StatelessWidget {
final String message; const FlutterRouteWidget({this.message});
FlutterRouteWidget({this.message}); final String message;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('flutter_boost_example'), title: const Text('flutter_boost_example'),
), ),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -83,7 +86,7 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -83,7 +86,7 @@ class FlutterRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 80.0), margin: const EdgeInsets.only(top: 80.0),
child: Text( child: Text(
message ?? "This is a flutter activity", message ?? 'This is a flutter activity',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -101,10 +104,12 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -101,10 +104,12 @@ class FlutterRouteWidget extends StatelessWidget {
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => onTap: () => FlutterBoost.singleton.open(
FlutterBoost.singleton.open("sample://nativePage", urlParams: <dynamic,dynamic>{ 'sample://nativePage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -118,10 +123,12 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -118,10 +123,12 @@ class FlutterRouteWidget extends StatelessWidget {
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => onTap: () => FlutterBoost.singleton.open(
FlutterBoost.singleton.open("sample://flutterPage", urlParams: <dynamic,dynamic>{ 'sample://flutterPage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'},
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -131,10 +138,13 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -131,10 +138,13 @@ class FlutterRouteWidget extends StatelessWidget {
child: Text( child: Text(
'push flutter widget', 'push flutter widget',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () { onTap: () {
Navigator.push<dynamic>( Navigator.push<dynamic>(
context, MaterialPageRoute<dynamic>(builder: (_) => PushWidget())); context,
MaterialPageRoute<dynamic>(builder: (_) => PushWidget()),
);
}, },
), ),
InkWell( InkWell(
...@@ -145,9 +155,10 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -145,9 +155,10 @@ class FlutterRouteWidget extends StatelessWidget {
child: Text( child: Text(
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () => onTap: () =>
FlutterBoost.singleton.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
), ),
], ],
), ),
...@@ -156,15 +167,15 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -156,15 +167,15 @@ class FlutterRouteWidget extends StatelessWidget {
} }
class FragmentRouteWidget extends StatelessWidget { class FragmentRouteWidget extends StatelessWidget {
final Map params; const FragmentRouteWidget(this.params);
FragmentRouteWidget(this.params); final Map<String, dynamic> params;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('flutter_boost_example'), title: const Text('flutter_boost_example'),
), ),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -172,7 +183,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -172,7 +183,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 80.0), margin: const EdgeInsets.only(top: 80.0),
child: Text( child: Text(
"This is a flutter fragment", 'This is a flutter fragment',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -180,7 +191,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -180,7 +191,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 32.0), margin: const EdgeInsets.only(top: 32.0),
child: Text( child: Text(
params['tag'] ?? '', '${params['tag']}' ?? '',
style: TextStyle(fontSize: 28.0, color: Colors.red), style: TextStyle(fontSize: 28.0, color: Colors.red),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -194,8 +205,9 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -194,8 +205,9 @@ class FragmentRouteWidget extends StatelessWidget {
child: Text( child: Text(
'open native page', 'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton.open("sample://nativePage"), ),
onTap: () => FlutterBoost.singleton.open('sample://nativePage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -205,8 +217,9 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -205,8 +217,9 @@ class FragmentRouteWidget extends StatelessWidget {
child: Text( child: Text(
'open flutter page', 'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton.open("sample://flutterPage"), ),
onTap: () => FlutterBoost.singleton.open('sample://flutterPage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -216,9 +229,10 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -216,9 +229,10 @@ class FragmentRouteWidget extends StatelessWidget {
child: Text( child: Text(
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () => onTap: () =>
FlutterBoost.singleton.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
) )
], ],
), ),
...@@ -234,15 +248,8 @@ class PushWidget extends StatefulWidget { ...@@ -234,15 +248,8 @@ class PushWidget extends StatefulWidget {
class _PushWidgetState extends State<PushWidget> { class _PushWidgetState extends State<PushWidget> {
VoidCallback _backPressedListenerUnsub; VoidCallback _backPressedListenerUnsub;
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override @override
void didChangeDependencies() { void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies(); super.didChangeDependencies();
// if (_backPressedListenerUnsub == null) { // if (_backPressedListenerUnsub == null) {
...@@ -258,13 +265,12 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -258,13 +265,12 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
void dispose() { void dispose() {
// TODO: implement dispose
super.dispose(); super.dispose();
_backPressedListenerUnsub?.call(); _backPressedListenerUnsub?.call();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FlutterRouteWidget(message: "Pushed Widget"); return const FlutterRouteWidget(message: 'Pushed Widget');
} }
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class TestPage extends StatefulWidget { class TestPage extends StatefulWidget {
TestPage({Key key, this.title = "Input Test"}) : super(key: key); const TestPage({
Key key,
this.title = 'Input Test',
}) : super(key: key);
final String title; final String title;
...@@ -18,24 +21,16 @@ class _TestPageState extends State<TestPage> { ...@@ -18,24 +21,16 @@ class _TestPageState extends State<TestPage> {
}); });
} }
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: Text(widget.title)),
title: Text(widget.title),
),
body: SafeArea( body: SafeArea(
bottom: false, bottom: false,
child: ListView( child: ListView(
children: <Widget>[ children: <Widget>[
Container( Container(
child: Text( child: const Text(
'You have pushed the button this many times:', 'You have pushed the button this many times:',
), ),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
...@@ -50,10 +45,7 @@ class _TestPageState extends State<TestPage> { ...@@ -50,10 +45,7 @@ class _TestPageState extends State<TestPage> {
alignment: Alignment.center, alignment: Alignment.center,
), ),
Container( Container(
child: TextField( child: const TextField(minLines: 2, maxLines: 10),
minLines: 2,
maxLines: 10,
),
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
), ),
TestTextField(), TestTextField(),
...@@ -98,20 +90,18 @@ class _TestPageState extends State<TestPage> { ...@@ -98,20 +90,18 @@ class _TestPageState extends State<TestPage> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
), ),
Container( Container(
child: TextField( child: const TextField(minLines: 2, maxLines: 10),
minLines: 2,
maxLines: 10,
),
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
), ),
TestTextField(), TestTextField(),
], ],
)), ),
),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter, onPressed: _incrementCounter,
tooltip: 'Increment', tooltip: 'Increment',
child: Icon(Icons.add), child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods. ),
); );
} }
} }
...@@ -123,25 +113,24 @@ class TestTextField extends StatefulWidget { ...@@ -123,25 +113,24 @@ class TestTextField extends StatefulWidget {
class _TestTextFieldState extends State<TestTextField> { class _TestTextFieldState extends State<TestTextField> {
FocusNode _node; FocusNode _node;
PersistentBottomSheetController _controller; PersistentBottomSheetController<dynamic> _controller;
@override @override
void initState() { void initState() {
// TODO: implement initState
super.initState(); super.initState();
_node = FocusNode(); _node = FocusNode();
_node.addListener(() { _node.addListener(() {
if (_node.hasFocus) { if (_node.hasFocus) {
print('showBottomSheet'); print('showBottomSheet');
_controller = Scaffold.of(context) _controller = Scaffold.of(context).showBottomSheet<dynamic>(
.showBottomSheet<dynamic>((BuildContext ctx) => Container( (BuildContext ctx) => Container(
width: double.infinity, width: double.infinity,
height: 36.0, height: 36.0,
color: Colors.deepPurple, color: Colors.deepPurple,
)); ),
);
} else { } else {
if (_controller != null) { if (_controller != null) {
//Navigator.of(context).pop();
print('closeBottomSheet'); print('closeBottomSheet');
_controller.close(); _controller.close();
} }
......
...@@ -24,30 +24,30 @@ ...@@ -24,30 +24,30 @@
import 'dart:async'; import 'dart:async';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/services.dart';
typedef Future<dynamic> EventListener(String name, Map arguments); import 'package:flutter/services.dart';
typedef Future<dynamic> MethodHandler(MethodCall call);
class BoostChannel { typedef EventListener = Future<dynamic> Function(
final MethodChannel _methodChannel = MethodChannel("flutter_boost"); String name, Map<String, dynamic> arguments);
final Map<String, List<EventListener>> _eventListeners = Map(); typedef MethodHandler = Future<dynamic> Function(MethodCall call);
final Set<MethodHandler> _methodHandlers = Set();
class BoostChannel {
BoostChannel() { BoostChannel() {
_methodChannel.setMethodCallHandler((MethodCall call) { _methodChannel.setMethodCallHandler((MethodCall call) {
if (call.method == "__event__") { if (call.method == '__event__') {
String name = call.arguments["name"]; final String name = call.arguments['name'] as String;
Map arg = call.arguments["arguments"]; final Map<String, dynamic> arg =
List<EventListener> list = _eventListeners[name]; (call.arguments['arguments'] as Map<dynamic, dynamic>)
?.cast<String, dynamic>();
final List<EventListener> list = _eventListeners[name];
if (list != null) { if (list != null) {
for (EventListener l in list) { for (final EventListener l in list) {
l(name, arg); l(name, arg);
} }
} }
} else { } else {
for (MethodHandler handler in _methodHandlers) { for (final MethodHandler handler in _methodHandlers) {
handler(call); handler(call);
} }
} }
...@@ -56,37 +56,41 @@ class BoostChannel { ...@@ -56,37 +56,41 @@ class BoostChannel {
}); });
} }
void sendEvent(String name, Map arguments) { final MethodChannel _methodChannel = const MethodChannel('flutter_boost');
final Map<String, List<EventListener>> _eventListeners =
<String, List<EventListener>>{};
final Set<MethodHandler> _methodHandlers = <MethodHandler>{};
void sendEvent(String name, Map<String, dynamic> arguments) {
if (name == null) { if (name == null) {
return; return;
} }
if (arguments == null) { arguments ??= <String, dynamic>{};
arguments = Map<dynamic, dynamic>();
}
Map msg = Map<dynamic, dynamic>(); final Map<String, dynamic> msg = <String, dynamic>{};
msg["name"] = name; msg['name'] = name;
msg["arguments"] = arguments; msg['arguments'] = arguments;
_methodChannel.invokeMethod<dynamic>("__event__", msg); _methodChannel.invokeMethod<dynamic>('__event__', msg);
} }
Future<T> invokeMethod<T>(String method, [dynamic arguments]) async { Future<T> invokeMethod<T>(String method, [dynamic arguments]) async {
assert(method != "__event__"); assert(method != '__event__');
return _methodChannel.invokeMethod<T>(method, arguments); return _methodChannel.invokeMethod<T>(method, arguments);
} }
Future<List<T>> invokeListMethod<T>(String method, Future<List<T>> invokeListMethod<T>(String method,
[dynamic arguments]) async { [dynamic arguments]) async {
assert(method != "__event__"); assert(method != '__event__');
return _methodChannel.invokeListMethod<T>(method, arguments); return _methodChannel.invokeListMethod<T>(method, arguments);
} }
Future<Map<K, V>> invokeMapMethod<K, V>(String method, Future<Map<K, V>> invokeMapMethod<K, V>(String method,
[dynamic arguments]) async { [dynamic arguments]) async {
assert(method != "__event__"); assert(method != '__event__');
return _methodChannel.invokeMapMethod<K, V>(method, arguments); return _methodChannel.invokeMapMethod<K, V>(method, arguments);
} }
...@@ -94,9 +98,11 @@ class BoostChannel { ...@@ -94,9 +98,11 @@ class BoostChannel {
VoidCallback addEventListener(String name, EventListener listener) { VoidCallback addEventListener(String name, EventListener listener) {
assert(name != null && listener != null); assert(name != null && listener != null);
List<EventListener> list = _eventListeners[name]; List<EventListener> list;
list = _eventListeners[name];
if (list == null) { if (list == null) {
list = List(); list = <EventListener>[];
_eventListeners[name] = list; _eventListeners[name] = list;
} }
......
...@@ -22,10 +22,11 @@ ...@@ -22,10 +22,11 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'container_manager.dart';
import '../flutter_boost.dart'; import '../flutter_boost.dart';
import 'boost_page_route.dart';
import '../support/logger.dart'; import '../support/logger.dart';
import 'boost_page_route.dart';
import 'container_manager.dart';
enum ContainerLifeCycle { enum ContainerLifeCycle {
Init, Init,
...@@ -37,28 +38,31 @@ enum ContainerLifeCycle { ...@@ -37,28 +38,31 @@ enum ContainerLifeCycle {
Foreground Foreground
} }
typedef void BoostContainerLifeCycleObserver( typedef BoostContainerLifeCycleObserver = void Function(
ContainerLifeCycle state, BoostContainerSettings settings); ContainerLifeCycle state,
BoostContainerSettings settings,
);
class BoostContainer extends Navigator { class BoostContainer extends Navigator {
final BoostContainerSettings settings; const BoostContainer({
GlobalKey<BoostContainerState> key,
const BoostContainer(
{GlobalKey<BoostContainerState> key,
this.settings = const BoostContainerSettings(), this.settings = const BoostContainerSettings(),
String initialRoute, String initialRoute,
RouteFactory onGenerateRoute, RouteFactory onGenerateRoute,
RouteFactory onUnknownRoute, RouteFactory onUnknownRoute,
List<NavigatorObserver> observers}) List<NavigatorObserver> observers,
: super( }) : super(
key: key, key: key,
initialRoute: initialRoute, initialRoute: initialRoute,
onGenerateRoute: onGenerateRoute, onGenerateRoute: onGenerateRoute,
onUnknownRoute: onUnknownRoute, onUnknownRoute: onUnknownRoute,
observers: observers); observers: observers,
);
factory BoostContainer.copy(Navigator navigator, factory BoostContainer.copy(
[BoostContainerSettings settings = const BoostContainerSettings()]) => Navigator navigator, [
BoostContainerSettings settings = const BoostContainerSettings(),
]) =>
BoostContainer( BoostContainer(
key: GlobalKey<BoostContainerState>(), key: GlobalKey<BoostContainerState>(),
settings: settings, settings: settings,
...@@ -69,7 +73,9 @@ class BoostContainer extends Navigator { ...@@ -69,7 +73,9 @@ class BoostContainer extends Navigator {
); );
factory BoostContainer.obtain( factory BoostContainer.obtain(
Navigator navigator, BoostContainerSettings settings) => Navigator navigator,
BoostContainerSettings settings,
) =>
BoostContainer( BoostContainer(
key: GlobalKey<BoostContainerState>(), key: GlobalKey<BoostContainerState>(),
settings: settings, settings: settings,
...@@ -81,7 +87,8 @@ class BoostContainer extends Navigator { ...@@ -81,7 +87,8 @@ class BoostContainer extends Navigator {
uniqueId: settings.uniqueId, uniqueId: settings.uniqueId,
animated: false, animated: false,
settings: routeSettings, settings: routeSettings,
builder: settings.builder); builder: settings.builder,
);
} else { } else {
return navigator.onGenerateRoute(routeSettings); return navigator.onGenerateRoute(routeSettings);
} }
...@@ -90,7 +97,10 @@ class BoostContainer extends Navigator { ...@@ -90,7 +97,10 @@ class BoostContainer extends Navigator {
ContainerNavigatorObserver.bindContainerManager(), ContainerNavigatorObserver.bindContainerManager(),
HeroController(), HeroController(),
], ],
onUnknownRoute: navigator.onUnknownRoute); onUnknownRoute: navigator.onUnknownRoute,
);
final BoostContainerSettings settings;
@override @override
BoostContainerState createState() => BoostContainerState(); BoostContainerState createState() => BoostContainerState();
...@@ -121,7 +131,7 @@ class BoostContainerState extends NavigatorState { ...@@ -121,7 +131,7 @@ class BoostContainerState extends NavigatorState {
String get name => widget.settings.name; String get name => widget.settings.name;
Map get params => widget.settings.params; Map<String, dynamic> get params => widget.settings.params;
BoostContainerSettings get settings => widget.settings; BoostContainerSettings get settings => widget.settings;
...@@ -138,7 +148,7 @@ class BoostContainerState extends NavigatorState { ...@@ -138,7 +148,7 @@ class BoostContainerState extends NavigatorState {
ContainerNavigatorObserver findContainerNavigatorObserver( ContainerNavigatorObserver findContainerNavigatorObserver(
Navigator navigator) { Navigator navigator) {
for (NavigatorObserver observer in navigator.observers) { for (final NavigatorObserver observer in navigator.observers) {
if (observer is ContainerNavigatorObserver) { if (observer is ContainerNavigatorObserver) {
return observer; return observer;
} }
...@@ -153,11 +163,6 @@ class BoostContainerState extends NavigatorState { ...@@ -153,11 +163,6 @@ class BoostContainerState extends NavigatorState {
backPressedHandler = () => maybePop(); backPressedHandler = () => maybePop();
} }
@override
void didUpdateWidget(Navigator oldWidget) {
super.didUpdateWidget(oldWidget);
}
@override @override
void dispose() { void dispose() {
routerHistory.clear(); routerHistory.clear();
...@@ -172,7 +177,7 @@ class BoostContainerState extends NavigatorState { ...@@ -172,7 +177,7 @@ class BoostContainerState extends NavigatorState {
@override @override
Future<bool> maybePop<T extends Object>([T result]) async { Future<bool> maybePop<T extends Object>([T result]) async {
final Route<T> route = routerHistory.last; final Route<T> route = routerHistory.last as Route<T>;
final RoutePopDisposition disposition = await route.willPop(); final RoutePopDisposition disposition = await route.willPop();
if (mounted) { if (mounted) {
switch (disposition) { switch (disposition) {
...@@ -216,10 +221,10 @@ class BoostContainerState extends NavigatorState { ...@@ -216,10 +221,10 @@ class BoostContainerState extends NavigatorState {
Route<T> newRoute; Route<T> newRoute;
if (FlutterBoost.containerManager.prePushRoute != null) { if (FlutterBoost.containerManager.prePushRoute != null) {
newRoute = FlutterBoost.containerManager newRoute = FlutterBoost.containerManager
.prePushRoute(name, uniqueId, params, route); .prePushRoute<T>(name, uniqueId, params, route);
} }
Future<T> future = super.push<T>(newRoute ?? route); final Future<T> future = super.push<T>(newRoute ?? route);
routerHistory.add(route); routerHistory.add(route);
...@@ -233,25 +238,30 @@ class BoostContainerState extends NavigatorState { ...@@ -233,25 +238,30 @@ class BoostContainerState extends NavigatorState {
VoidCallback addLifeCycleObserver(BoostContainerLifeCycleObserver observer) { VoidCallback addLifeCycleObserver(BoostContainerLifeCycleObserver observer) {
return FlutterBoost.singleton.addBoostContainerLifeCycleObserver( return FlutterBoost.singleton.addBoostContainerLifeCycleObserver(
(ContainerLifeCycle state, BoostContainerSettings settings) { (
ContainerLifeCycle state,
BoostContainerSettings settings,
) {
if (settings.uniqueId == uniqueId) { if (settings.uniqueId == uniqueId) {
observer(state, settings); observer(state, settings);
} }
}); },
);
} }
} }
class BoostContainerSettings { class BoostContainerSettings {
const BoostContainerSettings({
this.uniqueId = 'default',
this.name = 'default',
this.params,
this.builder,
});
final String uniqueId; final String uniqueId;
final String name; final String name;
final Map params; final Map<String, dynamic> params;
final WidgetBuilder builder; final WidgetBuilder builder;
const BoostContainerSettings(
{this.uniqueId = 'default',
this.name = 'default',
this.params,
this.builder});
} }
class ContainerElement extends StatefulElement { class ContainerElement extends StatefulElement {
...@@ -259,13 +269,13 @@ class ContainerElement extends StatefulElement { ...@@ -259,13 +269,13 @@ class ContainerElement extends StatefulElement {
} }
class ContainerNavigatorObserver extends NavigatorObserver { class ContainerNavigatorObserver extends NavigatorObserver {
static final Set<NavigatorObserver> boostObservers = Set<NavigatorObserver>();
ContainerNavigatorObserver(); ContainerNavigatorObserver();
factory ContainerNavigatorObserver.bindContainerManager() => factory ContainerNavigatorObserver.bindContainerManager() =>
ContainerNavigatorObserver(); ContainerNavigatorObserver();
static final Set<NavigatorObserver> boostObservers = <NavigatorObserver>{};
VoidCallback addBoostNavigatorObserver(NavigatorObserver observer) { VoidCallback addBoostNavigatorObserver(NavigatorObserver observer) {
boostObservers.add(observer); boostObservers.add(observer);
...@@ -278,28 +288,28 @@ class ContainerNavigatorObserver extends NavigatorObserver { ...@@ -278,28 +288,28 @@ class ContainerNavigatorObserver extends NavigatorObserver {
@override @override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
for (NavigatorObserver observer in boostObservers) { for (final NavigatorObserver observer in boostObservers) {
observer.didPush(route, previousRoute); observer.didPush(route, previousRoute);
} }
} }
@override @override
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) { void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
for (NavigatorObserver observer in boostObservers) { for (final NavigatorObserver observer in boostObservers) {
observer.didPop(route, previousRoute); observer.didPop(route, previousRoute);
} }
} }
@override @override
void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) { void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) {
for (NavigatorObserver observer in boostObservers) { for (final NavigatorObserver observer in boostObservers) {
observer.didRemove(route, previousRoute); observer.didRemove(route, previousRoute);
} }
} }
@override @override
void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) { void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
for (NavigatorObserver observer in boostObservers) { for (final NavigatorObserver observer in boostObservers) {
observer.didReplace(newRoute: newRoute, oldRoute: oldRoute); observer.didReplace(newRoute: newRoute, oldRoute: oldRoute);
} }
} }
......
...@@ -25,26 +25,25 @@ ...@@ -25,26 +25,25 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
typedef Widget PageBuilder(String pageName, Map params, String uniqueId); typedef PageBuilder = Widget Function(
String pageName, Map<String, dynamic> params, String uniqueId);
class BoostPageRoute<T> extends MaterialPageRoute<T> { class BoostPageRoute<T> extends MaterialPageRoute<T> {
BoostPageRoute({
this.pageName,
this.params,
this.uniqueId,
this.animated,
WidgetBuilder builder,
RouteSettings settings,
}) : super(builder: builder, settings: settings);
final String pageName; final String pageName;
final String uniqueId; final String uniqueId;
final Map params; final Map<String, dynamic> params;
final bool animated; final bool animated;
final WidgetBuilder builder;
final RouteSettings settings;
final Set<VoidCallback> backPressedListeners = Set<VoidCallback>(); final Set<VoidCallback> backPressedListeners = <VoidCallback>{};
BoostPageRoute(
{this.pageName,
this.params,
this.uniqueId,
this.animated,
this.builder,
this.settings})
: super(builder: builder, settings: settings);
static BoostPageRoute<T> of<T>(BuildContext context) { static BoostPageRoute<T> of<T>(BuildContext context) {
final Route<T> route = ModalRoute.of(context); final Route<T> route = ModalRoute.of(context);
......
...@@ -27,12 +27,25 @@ import 'dart:io'; ...@@ -27,12 +27,25 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart'; import 'package:flutter/semantics.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import '../channel/boost_channel.dart'; import '../channel/boost_channel.dart';
import 'boost_container.dart';
import '../flutter_boost.dart'; import '../flutter_boost.dart';
import '../support/logger.dart'; import '../support/logger.dart';
import 'boost_container.dart';
class ContainerCoordinator { class ContainerCoordinator {
ContainerCoordinator(BoostChannel channel) : assert(_instance == null) {
_instance = this;
channel
..addEventListener(
'lifecycle',
(String name, Map<String, dynamic> arguments) =>
_onChannelEvent(arguments),
)
..addMethodHandler((MethodCall call) => _onMethodCall(call));
}
static ContainerCoordinator get singleton => _instance; static ContainerCoordinator get singleton => _instance;
static ContainerCoordinator _instance; static ContainerCoordinator _instance;
...@@ -40,19 +53,11 @@ class ContainerCoordinator { ...@@ -40,19 +53,11 @@ class ContainerCoordinator {
final Map<String, PageBuilder> _pageBuilders = <String, PageBuilder>{}; final Map<String, PageBuilder> _pageBuilders = <String, PageBuilder>{};
PageBuilder _defaultPageBuilder; PageBuilder _defaultPageBuilder;
ContainerCoordinator(BoostChannel channel) {
assert(_instance == null);
_instance = this;
channel.addEventListener("lifecycle",
(String name, Map arguments) => _onChannelEvent(arguments));
channel.addMethodHandler((MethodCall call) => _onMethodCall(call));
}
BoostContainerSettings _createContainerSettings( BoostContainerSettings _createContainerSettings(
String name, Map params, String pageId) { String name,
Map<String, dynamic> params,
String pageId,
) {
Widget page; Widget page;
final BoostContainerSettings routeSettings = BoostContainerSettings( final BoostContainerSettings routeSettings = BoostContainerSettings(
...@@ -60,12 +65,12 @@ class ContainerCoordinator { ...@@ -60,12 +65,12 @@ class ContainerCoordinator {
name: name, name: name,
params: params, params: params,
builder: (BuildContext ctx) { builder: (BuildContext ctx) {
//Try to build a page using keyed builder. // Try to build a page using keyed builder.
if (_pageBuilders[name] != null) { if (_pageBuilders[name] != null) {
page = _pageBuilders[name](name, params, pageId); page = _pageBuilders[name](name, params, pageId);
} }
//Build a page using default builder. // Build a page using default builder.
if (page == null && _defaultPageBuilder != null) { if (page == null && _defaultPageBuilder != null) {
page = _defaultPageBuilder(name, params, pageId); page = _defaultPageBuilder(name, params, pageId);
} }
...@@ -79,12 +84,12 @@ class ContainerCoordinator { ...@@ -79,12 +84,12 @@ class ContainerCoordinator {
return routeSettings; return routeSettings;
} }
//Register a default page builder. /// Register a default page builder.
void registerDefaultPageBuilder(PageBuilder builder) { void registerDefaultPageBuilder(PageBuilder builder) {
_defaultPageBuilder = builder; _defaultPageBuilder = builder;
} }
//Register page builder for a key. /// Register page builder for a key.
void registerPageBuilder(String pageName, PageBuilder builder) { void registerPageBuilder(String pageName, PageBuilder builder) {
if (pageName != null && builder != null) { if (pageName != null && builder != null) {
_pageBuilders[pageName] = builder; _pageBuilders[pageName] = builder;
...@@ -98,41 +103,35 @@ class ContainerCoordinator { ...@@ -98,41 +103,35 @@ class ContainerCoordinator {
} }
Future<dynamic> _onChannelEvent(dynamic event) { Future<dynamic> _onChannelEvent(dynamic event) {
if (event is Map) { if (event is Map<String, dynamic>) {
Map map = event; final Map<String, dynamic> map = event;
final String type = map['type']; final String type = map['type'] as String;
Logger.log('onEvent $type'); Logger.log('onEvent $type');
switch (type) { switch (type) {
//Handler back key pressed event. // Handler back key pressed event.
case 'backPressedCallback': case 'backPressedCallback':
{ final String id = map['uniqueId'] as String;
final String id = map['uniqueId'];
FlutterBoost.containerManager FlutterBoost.containerManager
?.containerStateOf(id) ?.containerStateOf(id)
?.performBackPressed(); ?.performBackPressed();
}
break; break;
//Enter foregroud // Enter foreground
case 'foreground': case 'foreground':
{
FlutterBoost.containerManager?.setForeground(); FlutterBoost.containerManager?.setForeground();
}
break; break;
//Enter background // Enter background
case 'background': case 'background':
{
FlutterBoost.containerManager?.setBackground(); FlutterBoost.containerManager?.setBackground();
}
break; break;
//Schedule a frame. // Schedule a frame.
case 'scheduleFrame': case 'scheduleFrame':
{
WidgetsBinding.instance.scheduleForcedFrame(); WidgetsBinding.instance.scheduleForcedFrame();
Future<dynamic>.delayed(Duration(milliseconds: 250), Future<dynamic>.delayed(
() => WidgetsBinding.instance.scheduleFrame()); const Duration(milliseconds: 250),
} () => WidgetsBinding.instance.scheduleFrame(),
);
break; break;
} }
} }
...@@ -141,72 +140,52 @@ class ContainerCoordinator { ...@@ -141,72 +140,52 @@ class ContainerCoordinator {
} }
Future<dynamic> _onMethodCall(MethodCall call) { Future<dynamic> _onMethodCall(MethodCall call) {
Logger.log("onMetohdCall ${call.method}"); Logger.log('onMetohdCall ${call.method}');
final String pageName = call.arguments['pageName'] as String;
final Map<String, dynamic> params =
(call.arguments['params'] as Map<dynamic, dynamic>)
?.cast<String, dynamic>();
final String uniqueId = call.arguments['uniqueId'] as String;
switch (call.method) { switch (call.method) {
case "didInitPageContainer": case 'didInitPageContainer':
{
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerDidInit(pageName, params, uniqueId); _nativeContainerDidInit(pageName, params, uniqueId);
}
break; break;
case "willShowPageContainer": case 'willShowPageContainer':
{
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerWillShow(pageName, params, uniqueId); _nativeContainerWillShow(pageName, params, uniqueId);
}
break; break;
case "didShowPageContainer": case 'didShowPageContainer':
{
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
nativeContainerDidShow(pageName, params, uniqueId); nativeContainerDidShow(pageName, params, uniqueId);
}
break; break;
case "willDisappearPageContainer": case 'willDisappearPageContainer':
{
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerWillDisappear(pageName, params, uniqueId); _nativeContainerWillDisappear(pageName, params, uniqueId);
}
break; break;
case "didDisappearPageContainer": case 'didDisappearPageContainer':
{
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerDidDisappear(pageName, params, uniqueId); _nativeContainerDidDisappear(pageName, params, uniqueId);
}
break; break;
case "willDeallocPageContainer": case 'willDeallocPageContainer':
{
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerWillDealloc(pageName, params, uniqueId); _nativeContainerWillDealloc(pageName, params, uniqueId);
}
break; break;
case "onNativePageResult": case 'onNativePageResult':
{}
break; break;
} }
return Future<dynamic>(() {}); return Future<dynamic>(() {});
} }
bool _nativeContainerWillShow(String name, Map params, String pageId) { bool _nativeContainerWillShow(
String name,
Map<String, dynamic> params,
String pageId,
) {
if (FlutterBoost.containerManager?.containsContainer(pageId) != true) { if (FlutterBoost.containerManager?.containsContainer(pageId) != true) {
FlutterBoost.containerManager FlutterBoost.containerManager?.pushContainer(
?.pushContainer(_createContainerSettings(name, params, pageId)); _createContainerSettings(name, params, pageId),
);
} }
//TODO, 需要验证android代码是否也可以移到这里 // TODO(unknown): 需要验证android代码是否也可以移到这里
if (Platform.isIOS) { if (Platform.isIOS) {
try { try {
final SemanticsOwner owner = final SemanticsOwner owner =
...@@ -221,11 +200,16 @@ class ContainerCoordinator { ...@@ -221,11 +200,16 @@ class ContainerCoordinator {
return true; return true;
} }
bool nativeContainerDidShow(String name, Map params, String pageId) { bool nativeContainerDidShow(
String name,
Map<String, dynamic> params,
String pageId,
) {
FlutterBoost.containerManager FlutterBoost.containerManager
?.showContainer(_createContainerSettings(name, params, pageId)); ?.showContainer(_createContainerSettings(name, params, pageId));
//对无障碍辅助模式的兼容 // Compatible to accessibility mode on Android.
if (Platform.isAndroid) {
try { try {
final SemanticsOwner owner = final SemanticsOwner owner =
WidgetsBinding.instance.pipelineOwner?.semanticsOwner; WidgetsBinding.instance.pipelineOwner?.semanticsOwner;
...@@ -235,58 +219,95 @@ class ContainerCoordinator { ...@@ -235,58 +219,95 @@ class ContainerCoordinator {
} catch (e) { } catch (e) {
assert(false, e.toString()); assert(false, e.toString());
} }
}
performContainerLifeCycle(_createContainerSettings(name, params, pageId), performContainerLifeCycle(
ContainerLifeCycle.Appear); _createContainerSettings(name, params, pageId),
ContainerLifeCycle.Appear,
);
Logger.log( Logger.log(
'native containner did show-$name,\nmanager dump:\n${FlutterBoost.containerManager?.dump()}'); 'native containner did show-$name,\n'
'manager dump:\n'
'${FlutterBoost.containerManager?.dump()}',
);
return true; return true;
} }
bool _nativeContainerWillDisappear(String name, Map params, String pageId) { bool _nativeContainerWillDisappear(
performContainerLifeCycle(_createContainerSettings(name, params, pageId), String name,
ContainerLifeCycle.WillDisappear); Map<String, dynamic> params,
String pageId,
) {
performContainerLifeCycle(
_createContainerSettings(name, params, pageId),
ContainerLifeCycle.WillDisappear,
);
return true; return true;
} }
bool _nativeContainerDidDisappear(String name, Map params, String pageId) { bool _nativeContainerDidDisappear(
performContainerLifeCycle(_createContainerSettings(name, params, pageId), String name,
ContainerLifeCycle.Disappear); Map<String, dynamic> params,
String pageId,
) {
performContainerLifeCycle(
_createContainerSettings(name, params, pageId),
ContainerLifeCycle.Disappear,
);
return true; return true;
} }
bool _nativeContainerDidInit(String name, Map params, String pageId) { bool _nativeContainerDidInit(
performContainerLifeCycle(_createContainerSettings(name, params, pageId), String name,
ContainerLifeCycle.Init); Map<String, dynamic> params,
String pageId,
) {
performContainerLifeCycle(
_createContainerSettings(name, params, pageId),
ContainerLifeCycle.Init,
);
return true; return true;
} }
bool _nativeContainerWillDealloc(String name, Map params, String pageId) { bool _nativeContainerWillDealloc(
String name, Map<String, dynamic> params, String pageId) {
try { try {
performContainerLifeCycle(_createContainerSettings(name, params, pageId), performContainerLifeCycle(
ContainerLifeCycle.Destroy); _createContainerSettings(name, params, pageId),
ContainerLifeCycle.Destroy,
);
} catch (e) { } catch (e) {
Logger.log('nativeContainerWillDealloc error: $e'); Logger.log('nativeContainerWillDealloc error: $e');
} }
FlutterBoost.containerManager?.remove(pageId); FlutterBoost.containerManager?.remove(pageId);
Logger.log( Logger.log(
'native containner dealloc for $name, \n manager dump:\n${FlutterBoost.containerManager?.dump()}'); 'native containner dealloc for $name, \n'
'manager dump:\n'
'${FlutterBoost.containerManager?.dump()}',
);
return true; return true;
} }
static void performContainerLifeCycle( static void performContainerLifeCycle(
BoostContainerSettings settings, ContainerLifeCycle lifeCycle) { BoostContainerSettings settings,
for (BoostContainerLifeCycleObserver observer in FlutterBoost ContainerLifeCycle lifeCycle,
) {
final Set<BoostContainerLifeCycleObserver> observers = FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerLifeCycleObserver>()) { .observersOf<BoostContainerLifeCycleObserver>();
for (final BoostContainerLifeCycleObserver observer in observers) {
observer(lifeCycle, settings); observer(lifeCycle, settings);
} }
Logger.log( Logger.log(
'BoostContainerLifeCycleObserver container:${settings.name} lifeCycle:$lifeCycle'); 'BoostContainerLifeCycleObserver'
'container:${settings.name}'
'lifeCycle:$lifeCycle',
);
} }
} }
...@@ -23,10 +23,11 @@ ...@@ -23,10 +23,11 @@
*/ */
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'boost_container.dart';
import 'container_coordinator.dart';
import '../flutter_boost.dart'; import '../flutter_boost.dart';
import '../support/logger.dart'; import '../support/logger.dart';
import 'boost_container.dart';
import 'container_coordinator.dart';
enum ContainerOperation { Push, Onstage, Pop, Remove } enum ContainerOperation { Push, Onstage, Pop, Remove }
...@@ -35,12 +36,16 @@ typedef BoostContainerObserver = void Function( ...@@ -35,12 +36,16 @@ typedef BoostContainerObserver = void Function(
@immutable @immutable
class BoostContainerManager extends StatefulWidget { class BoostContainerManager extends StatefulWidget {
const BoostContainerManager({
Key key,
this.initNavigator,
this.prePushRoute,
this.postPushRoute,
}) : super(key: key);
final Navigator initNavigator; final Navigator initNavigator;
final PrePushRoute prePushRoute; final PrePushRoute prePushRoute;
final PostPushRoute postPushRoute; final PostPushRoute postPushRoute;
const BoostContainerManager(
{Key key, this.initNavigator, this.prePushRoute, this.postPushRoute})
: super(key: key);
@override @override
ContainerManagerState createState() => ContainerManagerState(); ContainerManagerState createState() => ContainerManagerState();
...@@ -76,15 +81,15 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -76,15 +81,15 @@ class ContainerManagerState extends State<BoostContainerManager> {
bool get foreground => _foreground; bool get foreground => _foreground;
//Number of containers. // Number of containers.
int get containerCounts => _offstage.length; int get containerCounts => _offstage.length;
List<BoostContainer> get offstage => _offstage; List<BoostContainer> get offstage => _offstage;
//Setting for current visible container. // Setting for current visible container.
BoostContainerSettings get onstageSettings => _onstage.settings; BoostContainerSettings get onstageSettings => _onstage.settings;
//Current visible container. // Current visible container.
BoostContainerState get onstageContainer => _stateOf(_onstage); BoostContainerState get onstageContainer => _stateOf(_onstage);
BoostContainerState get subContainer => BoostContainerState get subContainer =>
...@@ -118,8 +123,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -118,8 +123,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
} }
BoostContainerState _stateOf(BoostContainer container) { BoostContainerState _stateOf(BoostContainer container) {
if (container.key != null && if (container.key is GlobalKey<BoostContainerState>) {
container.key is GlobalKey<BoostContainerState>) {
final GlobalKey<BoostContainerState> globalKey = final GlobalKey<BoostContainerState> globalKey =
container.key as GlobalKey<BoostContainerState>; container.key as GlobalKey<BoostContainerState>;
return globalKey.currentState; return globalKey.currentState;
...@@ -133,7 +137,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -133,7 +137,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
void _onShownContainerChanged(String old, String now) { void _onShownContainerChanged(String old, String now) {
Logger.log('onShownContainerChanged old:$old now:$now'); Logger.log('onShownContainerChanged old:$old now:$now');
Map<String, dynamic> properties = new Map<String, dynamic>(); final Map<String, dynamic> properties = <String, dynamic>{};
properties['newName'] = now; properties['newName'] = now;
properties['oldName'] = old; properties['oldName'] = old;
...@@ -149,7 +153,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -149,7 +153,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
} }
if (_leastEntries != null && _leastEntries.isNotEmpty) { if (_leastEntries != null && _leastEntries.isNotEmpty) {
for (_ContainerOverlayEntry entry in _leastEntries) { for (final _ContainerOverlayEntry entry in _leastEntries) {
entry.remove(); entry.remove();
} }
} }
...@@ -223,7 +227,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -223,7 +227,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
setState(() {}); setState(() {});
for (BoostContainerObserver observer in FlutterBoost for (final BoostContainerObserver observer in FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerObserver>()) { .observersOf<BoostContainerObserver>()) {
observer(ContainerOperation.Onstage, _onstage.settings); observer(ContainerOperation.Onstage, _onstage.settings);
...@@ -265,7 +269,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -265,7 +269,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
setState(() {}); setState(() {});
for (BoostContainerObserver observer in FlutterBoost for (final BoostContainerObserver observer in FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerObserver>()) { .observersOf<BoostContainerObserver>()) {
observer(ContainerOperation.Push, _onstage.settings); observer(ContainerOperation.Push, _onstage.settings);
...@@ -280,9 +284,11 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -280,9 +284,11 @@ class ContainerManagerState extends State<BoostContainerManager> {
_onstage = _offstage.removeLast(); _onstage = _offstage.removeLast();
setState(() {}); setState(() {});
for (BoostContainerObserver observer in FlutterBoost final Set<BoostContainerObserver> observers = FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerObserver>()) { .observersOf<BoostContainerObserver>();
for (final BoostContainerObserver observer in observers) {
observer(ContainerOperation.Pop, old.settings); observer(ContainerOperation.Pop, old.settings);
} }
...@@ -295,31 +301,33 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -295,31 +301,33 @@ class ContainerManagerState extends State<BoostContainerManager> {
} else { } else {
final BoostContainer container = _offstage.firstWhere( final BoostContainer container = _offstage.firstWhere(
(BoostContainer container) => container.settings.uniqueId == uniqueId, (BoostContainer container) => container.settings.uniqueId == uniqueId,
orElse: () => null); orElse: () => null,
);
if (container != null) { if (container != null) {
_offstage.remove(container); _offstage.remove(container);
setState(() {}); setState(() {});
for (BoostContainerObserver observer in FlutterBoost final Set<BoostContainerObserver> observers = FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerObserver>()) { .observersOf<BoostContainerObserver>();
for (final BoostContainerObserver observer in observers) {
observer(ContainerOperation.Remove, container.settings); observer(ContainerOperation.Remove, container.settings);
} }
Logger.log('ContainerObserver#2 didRemove'); Logger.log('ContainerObserver#2 didRemove');
} }
} }
return null;
} }
bool canPop() => _offstage.isNotEmpty; bool canPop() => _offstage.isNotEmpty;
String dump() { String dump() {
String info = 'onstage#:\n ${_onstage?.desc()}\noffstage#:'; String info;
info = 'onstage#:\n ${_onstage?.desc()}\noffstage#:';
for (BoostContainer container in _offstage.reversed) { for (final BoostContainer container in _offstage.reversed) {
info = '$info\n ${container?.desc()}'; info = '$info\n ${container?.desc()}';
} }
...@@ -328,21 +336,21 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -328,21 +336,21 @@ class ContainerManagerState extends State<BoostContainerManager> {
} }
class _ContainerOverlayEntry extends OverlayEntry { class _ContainerOverlayEntry extends OverlayEntry {
bool _removed = false;
_ContainerOverlayEntry(BoostContainer container) _ContainerOverlayEntry(BoostContainer container)
: super( : super(
builder: (BuildContext ctx) => container, builder: (BuildContext ctx) => container,
opaque: true, opaque: true,
maintainState: true); maintainState: true,
);
bool _removed = false;
@override @override
void remove() { void remove() {
assert(!_removed); assert(!_removed);
if (_removed) { if (_removed) {
return; return;
} }
_removed = true; _removed = true;
super.remove(); super.remove();
} }
......
...@@ -25,58 +25,79 @@ import 'dart:async'; ...@@ -25,58 +25,79 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'container/boost_container.dart';
import 'container/container_manager.dart';
import 'channel/boost_channel.dart'; import 'channel/boost_channel.dart';
import 'container/boost_container.dart';
import 'container/container_coordinator.dart'; import 'container/container_coordinator.dart';
import 'container/container_manager.dart';
import 'observers_holders.dart'; import 'observers_holders.dart';
export 'container/boost_container.dart'; export 'container/boost_container.dart';
export 'container/container_manager.dart'; export 'container/container_manager.dart';
typedef Widget PageBuilder(String pageName, Map params, String uniqueId); typedef PageBuilder = Widget Function(
String pageName, Map<String, dynamic> params, String uniqueId);
typedef Route PrePushRoute( typedef PrePushRoute = Route<T> Function<T>(String url, String uniqueId,
String url, String uniqueId, Map params, Route route); Map<String, dynamic> params, Route<dynamic> route);
typedef void PostPushRoute( typedef PostPushRoute = void Function(
String url, String uniqueId, Map params, Route route, Future result); String url,
String uniqueId,
Map<String, dynamic> params,
Route<dynamic> route,
Future<dynamic> result,
);
class FlutterBoost { class FlutterBoost {
FlutterBoost() {
ContainerCoordinator(_boostChannel);
}
static final FlutterBoost _instance = FlutterBoost(); static final FlutterBoost _instance = FlutterBoost();
final GlobalKey<ContainerManagerState> containerManagerKey =
GlobalKey<ContainerManagerState>();
final ObserversHolder _observersHolder = ObserversHolder();
final BoostChannel _boostChannel = BoostChannel();
static FlutterBoost get singleton => _instance; static FlutterBoost get singleton => _instance;
static ContainerManagerState get containerManager => static ContainerManagerState get containerManager =>
_instance.containerManagerKey.currentState; _instance.containerManagerKey.currentState;
static void onPageStart() { final GlobalKey<ContainerManagerState> containerManagerKey =
WidgetsBinding.instance.addPostFrameCallback((_) { GlobalKey<ContainerManagerState>();
singleton.channel.invokeMethod<Map>('pageOnStart').then((Map pageInfo) { final ObserversHolder _observersHolder = ObserversHolder();
if (pageInfo == null || pageInfo.isEmpty) return; final BoostChannel _boostChannel = BoostChannel();
if (pageInfo.containsKey("name") && static void onPageStart() {
pageInfo.containsKey("params") && WidgetsBinding.instance.addPostFrameCallback((Duration _) {
pageInfo.containsKey("uniqueId")) { singleton.channel
.invokeMethod<Map<dynamic, dynamic>>('pageOnStart')
.then((Map<dynamic, dynamic> _pageInfo) {
final Map<String, dynamic> pageInfo = _pageInfo?.cast<String, dynamic>();
if (pageInfo?.isEmpty ?? true) {
return;
}
if (pageInfo.containsKey('name') &&
pageInfo.containsKey('params') &&
pageInfo.containsKey('uniqueId')) {
ContainerCoordinator.singleton.nativeContainerDidShow( ContainerCoordinator.singleton.nativeContainerDidShow(
pageInfo["name"], pageInfo["params"], pageInfo["uniqueId"]); pageInfo['name'] as String,
(pageInfo['params'] as Map<dynamic, dynamic>)
?.cast<String, dynamic>(),
pageInfo['uniqueId'] as String,
);
} }
}); });
}); });
} }
static TransitionBuilder init( static TransitionBuilder init({
{TransitionBuilder builder, TransitionBuilder builder,
PrePushRoute prePush, PrePushRoute prePush,
PostPushRoute postPush}) { PostPushRoute postPush,
}) {
if (Platform.isAndroid) { if (Platform.isAndroid) {
onPageStart(); onPageStart();
} else if (Platform.isIOS) { } else if (Platform.isIOS) {
// TODO(AlexVincent525): 未解之谜
assert(() { assert(() {
() async { () async {
onPageStart(); onPageStart();
...@@ -90,9 +111,10 @@ class FlutterBoost { ...@@ -90,9 +111,10 @@ class FlutterBoost {
final BoostContainerManager manager = BoostContainerManager( final BoostContainerManager manager = BoostContainerManager(
key: _instance.containerManagerKey, key: _instance.containerManagerKey,
initNavigator: child, initNavigator: child as Navigator,
prePushRoute: prePush, prePushRoute: prePush,
postPushRoute: postPush); postPushRoute: postPush,
);
if (builder != null) { if (builder != null) {
return builder(context, manager); return builder(context, manager);
...@@ -106,94 +128,95 @@ class FlutterBoost { ...@@ -106,94 +128,95 @@ class FlutterBoost {
BoostChannel get channel => _boostChannel; BoostChannel get channel => _boostChannel;
FlutterBoost() { /// Register a default page builder.
ContainerCoordinator(_boostChannel);
}
///Register a default page builder.
void registerDefaultPageBuilder(PageBuilder builder) { void registerDefaultPageBuilder(PageBuilder builder) {
ContainerCoordinator.singleton.registerDefaultPageBuilder(builder); ContainerCoordinator.singleton.registerDefaultPageBuilder(builder);
} }
///Register a map builders /// Register a map builders
void registerPageBuilders(Map<String, PageBuilder> builders) { void registerPageBuilders(Map<String, PageBuilder> builders) {
ContainerCoordinator.singleton.registerPageBuilders(builders); ContainerCoordinator.singleton.registerPageBuilders(builders);
} }
Future<Map<dynamic, dynamic>> open(String url, Future<Map<dynamic, dynamic>> open(
{Map<dynamic, dynamic> urlParams, Map<dynamic, dynamic> exts}) { String url, {
Map<dynamic, dynamic> properties = new Map<dynamic, dynamic>(); Map<String, dynamic> urlParams,
properties["url"] = url; Map<String, dynamic> exts,
properties["urlParams"] = urlParams; }) {
properties["exts"] = exts; final Map<String, dynamic> properties = <String, dynamic>{};
properties['url'] = url;
properties['urlParams'] = urlParams;
properties['exts'] = exts;
return channel.invokeMethod<Map<dynamic, dynamic>>('openPage', properties); return channel.invokeMethod<Map<dynamic, dynamic>>('openPage', properties);
} }
Future<bool> close(String id, Future<bool> close(
{Map<dynamic, dynamic> result, Map<dynamic, dynamic> exts}) { String id, {
Map<String, dynamic> result,
Map<String, dynamic> exts,
}) {
assert(id != null); assert(id != null);
BoostContainerSettings settings = containerManager?.onstageSettings; final BoostContainerSettings settings = containerManager?.onstageSettings;
Map<dynamic, dynamic> properties = new Map<dynamic, dynamic>(); final Map<String, dynamic> properties = <String, dynamic>{};
if (exts == null) { exts ??= <String, dynamic>{};
exts = Map<dynamic, dynamic>();
}
exts["params"] = settings.params; exts['params'] = settings.params;
if (!exts.containsKey("animated")) { if (!exts.containsKey('animated')) {
exts["animated"] = true; exts['animated'] = true;
} }
properties["uniqueId"] = id; properties['uniqueId'] = id;
if (result != null) { if (result != null) {
properties["result"] = result; properties['result'] = result;
} }
if (exts != null) { if (exts != null) {
properties["exts"] = exts; properties['exts'] = exts;
} }
return channel.invokeMethod<bool>('closePage', properties); return channel.invokeMethod<bool>('closePage', properties);
} }
Future<bool> closeCurrent( Future<bool> closeCurrent({
{Map<String, dynamic> result, Map<String, dynamic> exts}) { Map<String, dynamic> result,
BoostContainerSettings settings = containerManager?.onstageSettings; Map<String, dynamic> exts,
if (exts == null) { }) {
exts = Map<String, dynamic>(); final BoostContainerSettings settings = containerManager?.onstageSettings;
} exts ??= <String, dynamic>{};
exts["params"] = settings.params; exts['params'] = settings.params;
if (!exts.containsKey("animated")) { if (!exts.containsKey('animated')) {
exts["animated"] = true; exts['animated'] = true;
} }
return close(settings.uniqueId, result: result, exts: exts); return close(settings.uniqueId, result: result, exts: exts);
} }
Future<bool> closeByContext(BuildContext context, Future<bool> closeByContext(
{Map<String, dynamic> result, Map<String, dynamic> exts}) { BuildContext context, {
BoostContainerSettings settings = containerManager?.onstageSettings; Map<String, dynamic> result,
if (exts == null) { Map<String, dynamic> exts,
exts = Map<String, dynamic>(); }) {
} final BoostContainerSettings settings = containerManager?.onstageSettings;
exts["params"] = settings.params; exts ??= <String, dynamic>{};
if (!exts.containsKey("animated")) { exts['params'] = settings.params;
exts["animated"] = true; if (!exts.containsKey('animated')) {
exts['animated'] = true;
} }
return close(settings.uniqueId, result: result, exts: exts); return close(settings.uniqueId, result: result, exts: exts);
} }
///register for Container changed callbacks /// Register for Container changed callbacks
VoidCallback addContainerObserver(BoostContainerObserver observer) => VoidCallback addContainerObserver(BoostContainerObserver observer) =>
_observersHolder.addObserver<BoostContainerObserver>(observer); _observersHolder.addObserver<BoostContainerObserver>(observer);
///register for Container lifecycle callbacks /// Register for Container lifecycle callbacks
VoidCallback addBoostContainerLifeCycleObserver( VoidCallback addBoostContainerLifeCycleObserver(
BoostContainerLifeCycleObserver observer) => BoostContainerLifeCycleObserver observer) =>
_observersHolder.addObserver<BoostContainerLifeCycleObserver>(observer); _observersHolder.addObserver<BoostContainerLifeCycleObserver>(observer);
///register callbacks for Navigators push & pop /// Register callbacks for [Navigator.push] & [Navigator.pop]
void addBoostNavigatorObserver(NavigatorObserver observer) => void addBoostNavigatorObserver(NavigatorObserver observer) =>
ContainerNavigatorObserver.boostObservers.add(observer); ContainerNavigatorObserver.boostObservers.add(observer);
} }
...@@ -24,10 +24,10 @@ ...@@ -24,10 +24,10 @@
import 'dart:ui'; import 'dart:ui';
class ObserversHolder { class ObserversHolder {
final Map<String, Set<dynamic>> _observers = Map<String, Set<dynamic>>(); final Map<String, Set<dynamic>> _observers = <String, Set<dynamic>>{};
VoidCallback addObserver<T>(T observer) { VoidCallback addObserver<T>(T observer) {
final Set<T> set = _observers[T.toString()] ?? Set<T>(); final Set<T> set = _observers[T.toString()] as Set<T> ?? <T>{};
set.add(observer); set.add(observer);
_observers[T.toString()] = set; _observers[T.toString()] = set;
...@@ -40,5 +40,5 @@ class ObserversHolder { ...@@ -40,5 +40,5 @@ class ObserversHolder {
void cleanObservers<T>(T observer) => _observers[T.toString()]?.clear(); void cleanObservers<T>(T observer) => _observers[T.toString()]?.clear();
Set<T> observersOf<T>() => _observers[T.toString()] ?? Set<T>(); Set<T> observersOf<T>() => _observers[T.toString()] as Set<T> ?? <T>{};
} }
...@@ -27,7 +27,6 @@ class Logger { ...@@ -27,7 +27,6 @@ class Logger {
print('FlutterBoost#$msg'); print('FlutterBoost#$msg');
return true; return true;
}()); }());
//print('FlutterBoost=>$msg');
} }
static void error(String msg) { static void error(String msg) {
......
...@@ -17,42 +17,7 @@ dev_dependencies: ...@@ -17,42 +17,7 @@ dev_dependencies:
sdk: flutter sdk: flutter
mockito: 4.1.1 mockito: 4.1.1
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
# The following section is specific to Flutter.
flutter: flutter:
plugin: plugin:
androidPackage: com.idlefish.flutterboost androidPackage: com.idlefish.flutterboost
pluginClass: FlutterBoostPlugin pluginClass: FlutterBoostPlugin
# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.io/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.
# To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.io/custom-fonts/#from-packages
import 'package:flutter_boost/channel/boost_channel.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_boost/channel/boost_channel.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
...@@ -22,13 +23,12 @@ void main() { ...@@ -22,13 +23,12 @@ void main() {
response = null; response = null;
test('sendEvent successfully', () async { test('sendEvent successfully', () async {
Map msg1 = Map<dynamic,dynamic>(); final Map<String, dynamic> msg1 = <String, dynamic>{};
BoostChannel().sendEvent("name", msg1); BoostChannel().sendEvent('name', msg1);
Map msg = Map<dynamic,dynamic>();
msg["name"] = "name";
msg["arguments"] = msg1;
final Map<String, dynamic> msg = <String, dynamic>{};
msg['name'] = 'name';
msg['arguments'] = msg1;
expect( expect(
log, log,
...@@ -36,13 +36,10 @@ void main() { ...@@ -36,13 +36,10 @@ void main() {
); );
}); });
test('invokeMethod successfully', () async { test('invokeMethod successfully', () async {
Map msg = <dynamic,dynamic>{}; final Map<String, dynamic> msg = <String, dynamic>{};
msg["test"] = "test"; msg['test'] = 'test';
BoostChannel().invokeMethod<dynamic>("__event__1", msg); BoostChannel().invokeMethod<dynamic>('__event__1', msg);
// expect(e, isException);
expect( expect(
log, log,
...@@ -50,11 +47,10 @@ void main() { ...@@ -50,11 +47,10 @@ void main() {
); );
}); });
test('invokeListMethod successfully', () async { test('invokeListMethod successfully', () async {
Map msg = <dynamic,dynamic>{}; final Map<String, dynamic> msg = <String, dynamic>{};
msg["test"] = "test"; msg['test'] = 'test';
var bb = await BoostChannel().invokeListMethod<dynamic>("__event__1", msg); await BoostChannel().invokeListMethod<dynamic>('__event__1', msg);
expect( expect(
log, log,
...@@ -62,11 +58,10 @@ void main() { ...@@ -62,11 +58,10 @@ void main() {
); );
}); });
test('invokeMapMethod successfully', () async { test('invokeMapMethod successfully', () async {
Map msg = <dynamic,dynamic>{}; final Map<String, dynamic> msg = <String, dynamic>{};
msg["test"] = "test"; msg['test'] = 'test';
BoostChannel().invokeMapMethod<dynamic,dynamic>("__event__1", msg); BoostChannel().invokeMapMethod<dynamic, dynamic>('__event__1', msg);
expect( expect(
log, log,
...@@ -75,9 +70,9 @@ void main() { ...@@ -75,9 +70,9 @@ void main() {
}); });
test('invokeMapMethod successfully', () async { test('invokeMapMethod successfully', () async {
Map msg = <dynamic,dynamic>{}; final Map<String, dynamic> msg = <String, dynamic>{};
msg["test"] = "test"; msg['test'] = 'test';
BoostChannel().invokeMapMethod<dynamic,dynamic>("__event__1", msg); BoostChannel().invokeMapMethod<dynamic, dynamic>('__event__1', msg);
expect( expect(
log, log,
...@@ -86,22 +81,24 @@ void main() { ...@@ -86,22 +81,24 @@ void main() {
}); });
test('addEventListener successfully', () async { test('addEventListener successfully', () async {
Function test = BoostChannel().addEventListener( final VoidCallback test = BoostChannel().addEventListener(
"addEventListener", (String name, Map arguments) async => "test"); 'addEventListener',
print("xxx" + test.toString()); (String name, Map<String, dynamic> arguments) async => 'test',
);
print('xxx' + test.toString());
expect( expect(
test.toString(), test.toString(),
"Closure: () => Null", 'Closure: () => Null',
); );
}); });
test('addMethodHandler successfully', () async { test('addMethodHandler successfully', () async {
Function test = BoostChannel().addMethodHandler(( final VoidCallback test = BoostChannel().addMethodHandler(
MethodCall call) async => "test"); (MethodCall call) async => 'test',
);
expect( expect(
test.toString(), test.toString(),
"Closure: () => Null", 'Closure: () => Null',
); );
}); });
}); });
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_boost/container/boost_container.dart'; // import 'package:flutter_boost/container/boost_container.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
class FirstWidget extends StatelessWidget { class FirstWidget extends StatelessWidget {
...@@ -149,11 +149,11 @@ void main() { ...@@ -149,11 +149,11 @@ void main() {
); );
await tester.pumpWidget(widget); await tester.pumpWidget(widget);
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
await tester.tap(find.byKey(targetKey)); await tester.tap(find.byKey(targetKey));
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(exception, isInstanceOf<FlutterError>()); expect(exception, isInstanceOf<FlutterError>());
expect('$exception', expect('$exception',
......
...@@ -49,8 +49,8 @@ void main() { ...@@ -49,8 +49,8 @@ void main() {
testWidgets( testWidgets(
'obtain BoostPageRoute through the BoostPageRoute.of(context) method', 'obtain BoostPageRoute through the BoostPageRoute.of(context) method',
(WidgetTester tester) async { (WidgetTester tester) async {
dynamic boostPageRoute; BoostPageRoute<dynamic> boostPageRoute;
dynamic boostPageRouteFindByOfMethod; BoostPageRoute<dynamic> boostPageRouteFindByOfMethod;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -58,10 +58,11 @@ void main() { ...@@ -58,10 +58,11 @@ void main() {
boostPageRoute = BoostPageRoute<void>( boostPageRoute = BoostPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) => Builder( builder: (BuildContext context) => Builder(
builder: (context) { builder: (BuildContext context) {
return FloatingActionButton( return FloatingActionButton(
onPressed: () { onPressed: () {
boostPageRouteFindByOfMethod = BoostPageRoute.of<dynamic>(context); boostPageRouteFindByOfMethod =
BoostPageRoute.of<dynamic>(context);
}, },
); );
}, },
...@@ -74,7 +75,7 @@ void main() { ...@@ -74,7 +75,7 @@ void main() {
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
// The route obtained from the ancestor node through the `of` method should be the same BoostPageRoute // The route obtained from the ancestor node through the `of` method should be the same BoostPageRoute
// as the originally created BoostPageRoute // as the originally created BoostPageRoute
...@@ -85,15 +86,15 @@ void main() { ...@@ -85,15 +86,15 @@ void main() {
'try to find BoostPageRoute through the BoostPageRoute.of(context) method, ' 'try to find BoostPageRoute through the BoostPageRoute.of(context) method, '
'but it doesn\'t exist, the method should throw an Exception', 'but it doesn\'t exist, the method should throw an Exception',
(WidgetTester tester) async { (WidgetTester tester) async {
dynamic contextCache; BuildContext contextCache;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
onGenerateRoute: (RouteSettings settings) { onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<dynamic>( return MaterialPageRoute<dynamic>(
settings: settings, settings: settings,
builder: (context) => Builder( builder: (BuildContext context) => Builder(
builder: (context) => FloatingActionButton( builder: (BuildContext context) => FloatingActionButton(
onPressed: () { onPressed: () {
contextCache = context; contextCache = context;
}, },
...@@ -104,7 +105,7 @@ void main() { ...@@ -104,7 +105,7 @@ void main() {
), ),
); );
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(() => BoostPageRoute.of<dynamic>(contextCache), throwsException); expect(() => BoostPageRoute.of<dynamic>(contextCache), throwsException);
}); });
...@@ -112,8 +113,8 @@ void main() { ...@@ -112,8 +113,8 @@ void main() {
testWidgets( testWidgets(
'obtain BoostPageRoute through the BoostPageRoute.tryOf(context) method', 'obtain BoostPageRoute through the BoostPageRoute.tryOf(context) method',
(WidgetTester tester) async { (WidgetTester tester) async {
dynamic boostPageRoute; BoostPageRoute<dynamic> boostPageRoute;
dynamic boostPageRouteFindByOfMethod; BoostPageRoute<dynamic> boostPageRouteFindByOfMethod;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -121,7 +122,7 @@ void main() { ...@@ -121,7 +122,7 @@ void main() {
boostPageRoute = BoostPageRoute<void>( boostPageRoute = BoostPageRoute<void>(
settings: settings, settings: settings,
builder: (BuildContext context) => Builder( builder: (BuildContext context) => Builder(
builder: (context) { builder: (BuildContext context) {
return FloatingActionButton( return FloatingActionButton(
onPressed: () { onPressed: () {
boostPageRouteFindByOfMethod = boostPageRouteFindByOfMethod =
...@@ -137,7 +138,7 @@ void main() { ...@@ -137,7 +138,7 @@ void main() {
); );
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
// The route obtained from the ancestor node through the `tryOf` method should be the same BoostPageRoute // The route obtained from the ancestor node through the `tryOf` method should be the same BoostPageRoute
// as the originally created BoostPageRoute // as the originally created BoostPageRoute
...@@ -149,7 +150,7 @@ void main() { ...@@ -149,7 +150,7 @@ void main() {
'try to find BoostPageRoute through the BoostPageRoute.tryOf(context) method, ' 'try to find BoostPageRoute through the BoostPageRoute.tryOf(context) method, '
'but it doesn\'t exist, the method should return null', 'but it doesn\'t exist, the method should return null',
(WidgetTester tester) async { (WidgetTester tester) async {
dynamic boostPageRouteFindByOfMethod; BoostPageRoute<dynamic> boostPageRouteFindByOfMethod;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -157,7 +158,7 @@ void main() { ...@@ -157,7 +158,7 @@ void main() {
return MaterialPageRoute<dynamic>( return MaterialPageRoute<dynamic>(
settings: settings, settings: settings,
builder: (BuildContext context) => Builder( builder: (BuildContext context) => Builder(
builder: (context) { builder: (BuildContext context) {
return FloatingActionButton( return FloatingActionButton(
onPressed: () { onPressed: () {
boostPageRouteFindByOfMethod = boostPageRouteFindByOfMethod =
...@@ -172,7 +173,7 @@ void main() { ...@@ -172,7 +173,7 @@ void main() {
); );
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(boostPageRouteFindByOfMethod, null); expect(boostPageRouteFindByOfMethod, null);
}); });
......
...@@ -6,9 +6,6 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -6,9 +6,6 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:flutter_boost/channel/boost_channel.dart'; import 'package:flutter_boost/channel/boost_channel.dart';
import 'package:flutter_boost/container/container_coordinator.dart'; import 'package:flutter_boost/container/container_coordinator.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'dart:typed_data';
class MockBoostChannel extends BoostChannel implements Mock { class MockBoostChannel extends BoostChannel implements Mock {
MethodHandler get testHandler => _testHandler; MethodHandler get testHandler => _testHandler;
...@@ -17,12 +14,14 @@ class MockBoostChannel extends BoostChannel implements Mock { ...@@ -17,12 +14,14 @@ class MockBoostChannel extends BoostChannel implements Mock {
MethodHandler _testHandler; MethodHandler _testHandler;
EventListener _testEventListener; EventListener _testEventListener;
@override
VoidCallback addEventListener(String name, EventListener listener) { VoidCallback addEventListener(String name, EventListener listener) {
_testEventListener = listener; _testEventListener = listener;
return super.addEventListener(name, listener); return super.addEventListener(name, listener);
} }
@override
VoidCallback addMethodHandler(MethodHandler handler) { VoidCallback addMethodHandler(MethodHandler handler) {
_testHandler = handler; _testHandler = handler;
return super.addMethodHandler(handler); return super.addMethodHandler(handler);
...@@ -31,26 +30,26 @@ class MockBoostChannel extends BoostChannel implements Mock { ...@@ -31,26 +30,26 @@ class MockBoostChannel extends BoostChannel implements Mock {
void main() { void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
const MessageCodec<dynamic> jsonMessage = JSONMessageCodec(); // const MessageCodec<dynamic> jsonMessage = JSONMessageCodec();
test('test onMethodCall', () async { test('test onMethodCall', () async {
// Initialize all bindings because defaultBinaryMessenger.send() needs a window. // Initialize all bindings because defaultBinaryMessenger.send() needs a window.
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
MockBoostChannel boostChannel = MockBoostChannel(); final MockBoostChannel boostChannel = MockBoostChannel();
ContainerCoordinator(boostChannel); ContainerCoordinator(boostChannel);
final Map arguments =<dynamic,dynamic> {}; final Map<String, dynamic> arguments = <String, dynamic>{};
arguments["pageName"] = "pageName"; arguments['pageName'] = 'pageName';
arguments["params"] = <dynamic,dynamic>{}; arguments['params'] = <dynamic, dynamic>{};
arguments["uniqueId"] = "xxxxx"; arguments['uniqueId'] = 'xxxxx';
MethodCall call = MethodCall('didInitPageContainer', arguments); final MethodCall call = MethodCall('didInitPageContainer', arguments);
try { try {
boostChannel.testHandler(call); boostChannel.testHandler(call);
} catch (e) { } catch (e) {
expect(e, isAssertionError); expect(e, isAssertionError);
} }
MethodCall call2 = MethodCall('willShowPageContainer', arguments); final MethodCall call2 = MethodCall('willShowPageContainer', arguments);
try { try {
boostChannel.testHandler(call2); boostChannel.testHandler(call2);
...@@ -58,7 +57,7 @@ void main() { ...@@ -58,7 +57,7 @@ void main() {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
MethodCall call3 = MethodCall('didShowPageContainer', arguments); final MethodCall call3 = MethodCall('didShowPageContainer', arguments);
try { try {
boostChannel.testHandler(call3); boostChannel.testHandler(call3);
...@@ -66,7 +65,8 @@ void main() { ...@@ -66,7 +65,8 @@ void main() {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
MethodCall call4 = MethodCall('willDisappearPageContainer', arguments); final MethodCall call4 =
MethodCall('willDisappearPageContainer', arguments);
try { try {
boostChannel.testHandler(call4); boostChannel.testHandler(call4);
...@@ -74,7 +74,7 @@ void main() { ...@@ -74,7 +74,7 @@ void main() {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
MethodCall call5 = MethodCall('onNativePageResult', arguments); final MethodCall call5 = MethodCall('onNativePageResult', arguments);
try { try {
boostChannel.testHandler(call5); boostChannel.testHandler(call5);
...@@ -82,14 +82,14 @@ void main() { ...@@ -82,14 +82,14 @@ void main() {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
MethodCall call6 = MethodCall('didDisappearPageContainer', arguments); final MethodCall call6 = MethodCall('didDisappearPageContainer', arguments);
try { try {
boostChannel.testHandler(call6); boostChannel.testHandler(call6);
} catch (e) { } catch (e) {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
MethodCall call7 = MethodCall('willDeallocPageContainer', arguments); final MethodCall call7 = MethodCall('willDeallocPageContainer', arguments);
try { try {
boostChannel.testHandler(call7); boostChannel.testHandler(call7);
...@@ -97,35 +97,36 @@ void main() { ...@@ -97,35 +97,36 @@ void main() {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
Map arg = <dynamic,dynamic>{'type': 'backPressedCallback'}; final Map<String, dynamic> arg = <String, dynamic>{
'type': 'backPressedCallback'
};
try { try {
boostChannel.testEventListener("lifecycle", arg); boostChannel.testEventListener('lifecycle', arg);
} catch (e) { } catch (e) {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
final Map<String, dynamic> arg2 = <String, dynamic>{'type': 'foreground'};
Map arg2 = <dynamic,dynamic>{'type': 'foreground'};
try { try {
boostChannel.testEventListener("lifecycle", arg2); boostChannel.testEventListener('lifecycle', arg2);
} catch (e) { } catch (e) {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
Map arg3 = <dynamic,dynamic>{'type': 'background'}; final Map<String, dynamic> arg3 = <String, dynamic>{'type': 'background'};
try { try {
boostChannel.testEventListener("lifecycle", arg3); boostChannel.testEventListener('lifecycle', arg3);
} catch (e) { } catch (e) {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
Map arg4 = <dynamic,dynamic>{'type': 'scheduleFrame'}; final Map<String, dynamic> arg4 = <String, dynamic>{
'type': 'scheduleFrame'
};
try { try {
boostChannel.testEventListener("lifecycle", arg4); boostChannel.testEventListener('lifecycle', arg4);
} catch (e) { } catch (e) {
expect(e, isNoSuchMethodError); expect(e, isNoSuchMethodError);
} }
}); });
} }
...@@ -12,19 +12,21 @@ class FirstRouteWidget extends StatelessWidget { ...@@ -12,19 +12,21 @@ class FirstRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('First Route'), title: const Text('First Route'),
), ),
body: Center( body: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
RaisedButton( RaisedButton(
child: Text('First'), child: const Text('First'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -40,19 +42,21 @@ class SecondRouteWidget extends StatelessWidget { ...@@ -40,19 +42,21 @@ class SecondRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Second Route'), title: const Text('Second Route'),
), ),
body: Center( body: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
RaisedButton( RaisedButton(
child: Text('Second'), child: const Text('Second'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -73,9 +77,11 @@ class _MyAppState extends State<MyApp> { ...@@ -73,9 +77,11 @@ class _MyAppState extends State<MyApp> {
void initState() { void initState() {
super.initState(); super.initState();
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(<String, PageBuilder>{
'first': (pageName, params, _) => FirstRouteWidget(), 'first': (String pageName, Map<String, dynamic> params, String _) =>
'second': (pageName, params, _) => SecondRouteWidget(), FirstRouteWidget(),
'second': (String pageName, Map<String, dynamic> params, String _) =>
SecondRouteWidget(),
}); });
} }
...@@ -88,7 +94,7 @@ class _MyAppState extends State<MyApp> { ...@@ -88,7 +94,7 @@ class _MyAppState extends State<MyApp> {
assert(child is Navigator, 'child must be Navigator, what is wrong?'); assert(child is Navigator, 'child must be Navigator, what is wrong?');
final BoostContainerManager manager = BoostContainerManager( final BoostContainerManager manager = BoostContainerManager(
initNavigator: child, initNavigator: child as Navigator,
); );
return manager; return manager;
...@@ -113,11 +119,14 @@ void main() { ...@@ -113,11 +119,14 @@ void main() {
testWidgets( testWidgets(
'through the `BoostContainerManager.of(context)` method', 'through the `BoostContainerManager.of(context)` method',
(WidgetTester tester) async { (WidgetTester tester) async {
var builderContext; BuildContext builderContext;
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(
'context': (pageName, params, _) => Builder( <String, PageBuilder>{
builder: (context) { 'context':
(String pageName, Map<String, dynamic> params, String _) =>
Builder(
builder: (BuildContext context) {
return FloatingActionButton( return FloatingActionButton(
onPressed: () { onPressed: () {
builderContext = context; builderContext = context;
...@@ -125,7 +134,8 @@ void main() { ...@@ -125,7 +134,8 @@ void main() {
); );
}, },
), ),
}); },
);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -135,28 +145,34 @@ void main() { ...@@ -135,28 +145,34 @@ void main() {
); );
//open context page //open context page
ContainerCoordinator.singleton ContainerCoordinator.singleton.nativeContainerDidShow(
.nativeContainerDidShow("context", {}, "1000000"); 'context',
<String, dynamic>{},
'1000000',
);
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(find.byType(FloatingActionButton), findsOneWidget); expect(find.byType(FloatingActionButton), findsOneWidget);
//get the context of the Builder //get the context of the Builder
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
final isFind = BoostContainerManager.of(builderContext) != null; final bool isFind = BoostContainerManager.of(builderContext) != null;
expect(isFind, true, expect(
isFind,
true,
reason: '`BoostContainerManager.of` should be able to ' reason: '`BoostContainerManager.of` should be able to '
'find `ContainerManagerState` in `FlutterBoost.init()` based on the context of the `Builder`'); 'find `ContainerManagerState` in `FlutterBoost.init()` based on the context of the `Builder`',
);
}, },
); );
// testWidgets( // testWidgets(
// 'through the `BoostContainerManager.of(context)` method', // 'through the `BoostContainerManager.of(context)` method',
// (WidgetTester tester) async { // (WidgetTester tester) async {
// var builderContext; // BuildContext builderContext;
// //
// await tester.pumpWidget( // await tester.pumpWidget(
// MaterialApp( // MaterialApp(
...@@ -184,11 +200,13 @@ void main() { ...@@ -184,11 +200,13 @@ void main() {
testWidgets( testWidgets(
'through the `BoostContainerManager.tryOf(context)` method', 'through the `BoostContainerManager.tryOf(context)` method',
(WidgetTester tester) async { (WidgetTester tester) async {
var builderContext; BuildContext builderContext;
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(
'context': (pageName, params, _) => Builder( <String, PageBuilder>{
builder: (context) { 'context': (String pageName, Map<String, dynamic> params, _) =>
Builder(
builder: (BuildContext context) {
return FloatingActionButton( return FloatingActionButton(
onPressed: () { onPressed: () {
builderContext = context; builderContext = context;
...@@ -196,7 +214,8 @@ void main() { ...@@ -196,7 +214,8 @@ void main() {
); );
}, },
), ),
}); },
);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -206,21 +225,25 @@ void main() { ...@@ -206,21 +225,25 @@ void main() {
); );
//open context page //open context page
ContainerCoordinator.singleton ContainerCoordinator.singleton.nativeContainerDidShow(
.nativeContainerDidShow("context", {}, "1000000"); 'context', <String, dynamic>{}, '1000000');
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(find.byType(FloatingActionButton), findsOneWidget); expect(find.byType(FloatingActionButton), findsOneWidget);
//get the context of the Builder //get the context of the Builder
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
final isFind = BoostContainerManager.tryOf(builderContext) != null; final bool isFind =
BoostContainerManager.tryOf(builderContext) != null;
expect(isFind, true, expect(
isFind,
true,
reason: '`BoostContainerManager.tryOf` should be able to ' reason: '`BoostContainerManager.tryOf` should be able to '
'find `ContainerManagerState` in `FlutterBoost.init()` based on the context of the `Builder`'); 'find `ContainerManagerState` in `FlutterBoost.init()` based on the context of the `Builder`',
);
}, },
); );
}, },
...@@ -230,11 +253,13 @@ void main() { ...@@ -230,11 +253,13 @@ void main() {
testWidgets( testWidgets(
'containerCounts should change based on the number of pages', 'containerCounts should change based on the number of pages',
(WidgetTester tester) async { (WidgetTester tester) async {
var builderContext; BuildContext builderContext;
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(
'context': (pageName, params, _) => Builder( <String, PageBuilder>{
builder: (context) { 'context': (String pageName, Map<String, dynamic> params, _) =>
Builder(
builder: (BuildContext context) {
return FloatingActionButton( return FloatingActionButton(
onPressed: () { onPressed: () {
builderContext = context; builderContext = context;
...@@ -242,7 +267,8 @@ void main() { ...@@ -242,7 +267,8 @@ void main() {
); );
}, },
), ),
}); },
);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -253,23 +279,24 @@ void main() { ...@@ -253,23 +279,24 @@ void main() {
//open first context page //open first context page
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("context", {}, "1000000"); .nativeContainerDidShow('context', <String, dynamic>{}, '1000000');
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
//get the context of the Builder //get the context of the Builder
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
final containerManagerState = BoostContainerManager.of(builderContext); final ContainerManagerState containerManagerState =
BoostContainerManager.of(builderContext);
expect(containerManagerState.containerCounts, 1, expect(containerManagerState.containerCounts, 1,
reason: '1 page shown'); reason: '1 page shown');
//open second context page //open second context page
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("context", {}, "2000000"); .nativeContainerDidShow('context', <String, dynamic>{}, '2000000');
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(containerManagerState.containerCounts, 2, expect(containerManagerState.containerCounts, 2,
reason: '2 page shown'); reason: '2 page shown');
...@@ -277,7 +304,7 @@ void main() { ...@@ -277,7 +304,7 @@ void main() {
//pop second context page //pop second context page
containerManagerState.pop(); containerManagerState.pop();
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(containerManagerState.containerCounts, 1, expect(containerManagerState.containerCounts, 1,
reason: 'second context page closed, Only one page left'); reason: 'second context page closed, Only one page left');
...@@ -285,7 +312,7 @@ void main() { ...@@ -285,7 +312,7 @@ void main() {
//pop last context page //pop last context page
containerManagerState.pop(); containerManagerState.pop();
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(containerManagerState.containerCounts, 0, expect(containerManagerState.containerCounts, 0,
reason: 'last context page closed, no page left'); reason: 'last context page closed, no page left');
......
import 'package:flutter_boost/container/container_manager.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_boost/flutter_boost.dart'; import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_boost/container/container_manager.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
test('test onMethodCall', () async {
FlutterBoost.singleton.registerDefaultPageBuilder(
(String pageName, Map<String, dynamic> params, String _) =>
Container());
FlutterBoost.singleton.addContainerObserver(
(ContainerOperation operation, BoostContainerSettings settings) {},
);
FlutterBoost.singleton.addBoostContainerLifeCycleObserver(
(ContainerLifeCycle state, BoostContainerSettings settings) {},
);
FlutterBoost.singleton.addBoostNavigatorObserver(NavigatorObserver());
try {
FlutterBoost.singleton.open('url');
} catch (e) {
expect(e, isException);
}
try {
FlutterBoost.singleton.close('url');
} catch (e) {
expect(e, isNoSuchMethodError);
}
try {
FlutterBoost.singleton.closeCurrent(
result: <String, dynamic>{},
exts: <String, dynamic>{},
);
} catch (e) {
expect(e, isNoSuchMethodError);
}
// test('test onMethodCall', () async { try {
// FlutterBoost.singleton FlutterBoost.singleton.closeByContext(
// .registerDefaultPageBuilder((pageName, params, _) => Container()); null,
// FlutterBoost.singleton.addContainerObserver( result: <String, dynamic>{},
// (ContainerOperation operation, BoostContainerSettings settings) {}); exts: <String, dynamic>{},
// );
// FlutterBoost.singleton.addBoostContainerLifeCycleObserver( } catch (e) {
// (ContainerLifeCycle state, BoostContainerSettings settings) {}); expect(e, isNoSuchMethodError);
// }
// FlutterBoost.singleton.addBoostNavigatorObserver(NavigatorObserver()); });
//
// try {
// FlutterBoost.singleton.open("url");
// } catch (e) {
// expect(e, isException);
// }
// try {
// FlutterBoost.singleton.close("url");
// } catch (e) {
// expect(e, isNoSuchMethodError);
// }
// try {
// FlutterBoost.singleton.closeCurrent(result: <String,dynamic>{}, exts: <String,dynamic>{});
// } catch (e) {
// expect(e, isNoSuchMethodError);
// }
//
// try {
// FlutterBoost.singleton.closeByContext(null, result: <String,dynamic>{}, exts: <String,dynamic>{});
// } catch (e) {
// expect(e, isNoSuchMethodError);
// }
// });
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_boost/flutter_boost.dart'; import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_boost/container/container_coordinator.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'page_widgets.dart'; import 'page_widgets.dart';
import 'package:flutter_boost/container/container_coordinator.dart';
class MyApp extends StatefulWidget { class MyApp extends StatefulWidget {
@override @override
...@@ -15,14 +16,19 @@ class _MyAppState extends State<MyApp> { ...@@ -15,14 +16,19 @@ class _MyAppState extends State<MyApp> {
void initState() { void initState() {
super.initState(); super.initState();
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(<String, PageBuilder>{
'embeded': (pageName, params, _) => EmbededFirstRouteWidget(), 'embeded': (String pageName, Map<String, dynamic> params, _) =>
'first': (pageName, params, _) => FirstRouteWidget(), EmbededFirstRouteWidget(),
'second': (pageName, params, _) => SecondRouteWidget(), 'first': (String pageName, Map<String, dynamic> params, _) =>
'tab': (pageName, params, _) => TabRouteWidget(), FirstRouteWidget(),
'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params), 'second': (String pageName, Map<String, dynamic> params, _) =>
'flutterPage': (pageName, params, _) { SecondRouteWidget(),
print("flutterPage params:$params"); 'tab': (String pageName, Map<String, dynamic> params, _) =>
TabRouteWidget(),
'flutterFragment': (String pageName, Map<String, dynamic> params, _) =>
FragmentRouteWidget(params),
'flutterPage': (String pageName, Map<String, dynamic> params, _) {
print('flutterPage params:$params');
return FlutterRouteWidget(params: params); return FlutterRouteWidget(params: params);
}, },
...@@ -40,24 +46,33 @@ class _MyAppState extends State<MyApp> { ...@@ -40,24 +46,33 @@ class _MyAppState extends State<MyApp> {
} }
void _onRoutePushed( void _onRoutePushed(
String pageName, String uniqueId, Map params, Route route, Future _) {} String pageName,
String uniqueId,
Map<String, dynamic> params,
Route<dynamic> route,
Future<dynamic> _,
) {}
} }
class TestBoostNavigatorObserver extends NavigatorObserver { class TestBoostNavigatorObserver extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didPush"); print('flutterboost#didPush');
} }
@override
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) { void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didPop"); print('flutterboost#didPop');
} }
@override
void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) { void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didRemove"); print('flutterboost#didRemove');
} }
@override
void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) { void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
print("flutterboost#didReplace"); print('flutterboost#didReplace');
} }
} }
...@@ -72,7 +87,7 @@ void main() { ...@@ -72,7 +87,7 @@ void main() {
); );
//open firt page //open firt page
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("first", <dynamic,dynamic>{}, "1000000"); .nativeContainerDidShow('first', <String, dynamic>{}, '1000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -80,7 +95,7 @@ void main() { ...@@ -80,7 +95,7 @@ void main() {
//open second page firt(1000000)->second(2000000) //open second page firt(1000000)->second(2000000)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("second", <dynamic,dynamic>{}, "2000000"); .nativeContainerDidShow('second', <String, dynamic>{}, '2000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -89,7 +104,7 @@ void main() { ...@@ -89,7 +104,7 @@ void main() {
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
//close sencod page firt(1000000) //close sencod page firt(1000000)
FlutterBoost.containerManager?.remove("2000000"); FlutterBoost.containerManager?.remove('2000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -97,7 +112,7 @@ void main() { ...@@ -97,7 +112,7 @@ void main() {
// second page ,but pageId is 2000001 firt(1000000)->second(2000001) // second page ,but pageId is 2000001 firt(1000000)->second(2000001)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("second", <dynamic,dynamic>{}, "2000001"); .nativeContainerDidShow('second', <String, dynamic>{}, '2000001');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -107,7 +122,7 @@ void main() { ...@@ -107,7 +122,7 @@ void main() {
//reopen firt page second(2000001)->firt(1000000) //reopen firt page second(2000001)->firt(1000000)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("first",<dynamic,dynamic> {}, "1000000"); .nativeContainerDidShow('first', <String, dynamic>{}, '1000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -117,7 +132,7 @@ void main() { ...@@ -117,7 +132,7 @@ void main() {
// reopen second page and pageId is 2000001 firt(1000000)->second(2000001) // reopen second page and pageId is 2000001 firt(1000000)->second(2000001)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("second", <dynamic,dynamic>{}, "2000001"); .nativeContainerDidShow('second', <String, dynamic>{}, '2000001');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -126,24 +141,18 @@ void main() { ...@@ -126,24 +141,18 @@ void main() {
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
//close firt(1000000) page second(2000001) //close firt(1000000) page second(2000001)
FlutterBoost.containerManager?.remove("1000000"); FlutterBoost.containerManager?.remove('1000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(find.text('Second'), findsOneWidget); expect(find.text('Second'), findsOneWidget);
// open second(2000003) // open second(2000003)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("second", <dynamic,dynamic>{}, "2000003"); .nativeContainerDidShow('second', <String, dynamic>{}, '2000003');
await tester.idle(); await tester.idle();
expect(find.text('Second'), findsOneWidget); expect(find.text('Second'), findsOneWidget);
}); });
} }
...@@ -7,32 +7,34 @@ class FirstRouteWidget extends StatelessWidget { ...@@ -7,32 +7,34 @@ class FirstRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('First Route'), title: const Text('First Route'),
), ),
body: Center( body: Center(
child: child: Column(
Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: children: <Widget>[
<Widget>[
RaisedButton( RaisedButton(
child: Text('First'), child: const Text('First'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
RaisedButton( RaisedButton(
child: Text('Present second route'), child: const Text('Present second route'),
onPressed: () { onPressed: () {
print("Present second page!"); print('Present second page!');
FlutterBoost.singleton.open("second",urlParams:<dynamic,dynamic>{"present":true}).then((Map value) { FlutterBoost.singleton.open('second',
urlParams: <String, dynamic>{
'present': true
}).then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -49,12 +51,14 @@ class EmbededFirstRouteWidget extends StatelessWidget { ...@@ -49,12 +51,14 @@ class EmbededFirstRouteWidget extends StatelessWidget {
return Scaffold( return Scaffold(
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: Text('Open second route'), child: const Text('Open second route'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<dynamic, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -68,19 +72,19 @@ class SecondRouteWidget extends StatelessWidget { ...@@ -68,19 +72,19 @@ class SecondRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text("Second"), title: const Text('Second'),
), ),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
// Navigate back to first route when tapped. // Navigate back to first route when tapped.
BoostContainerSettings settings = final BoostContainerSettings settings =
BoostContainer.of(context).settings; BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId, FlutterBoost.singleton.close(settings.uniqueId,
result:<dynamic,dynamic>{"result": "data from second"}); result: <String, dynamic>{'result': 'data from second'});
}, },
child: Text('Go back with result!'), child: const Text('Go back with result!'),
), ),
), ),
); );
...@@ -92,14 +96,14 @@ class TabRouteWidget extends StatelessWidget { ...@@ -92,14 +96,14 @@ class TabRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text("Tab Route"), title: const Text('Tab Route'),
), ),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
FlutterBoost.singleton.open("second"); FlutterBoost.singleton.open('second');
}, },
child: Text('Open second route'), child: const Text('Open second route'),
), ),
), ),
); );
...@@ -107,8 +111,9 @@ class TabRouteWidget extends StatelessWidget { ...@@ -107,8 +111,9 @@ class TabRouteWidget extends StatelessWidget {
} }
class FlutterRouteWidget extends StatefulWidget { class FlutterRouteWidget extends StatefulWidget {
FlutterRouteWidget({this.params,this.message}); const FlutterRouteWidget({this.params, this.message});
final Map params;
final Map<String, dynamic> params;
final String message; final String message;
@override @override
...@@ -116,34 +121,31 @@ class FlutterRouteWidget extends StatefulWidget { ...@@ -116,34 +121,31 @@ class FlutterRouteWidget extends StatefulWidget {
} }
class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
final TextEditingController _usernameController = TextEditingController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final String message=widget.message; final String message = widget.message;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
brightness:Brightness.light, brightness: Brightness.light,
backgroundColor: Colors.white, backgroundColor: Colors.white,
textTheme:new TextTheme(title: TextStyle(color: Colors.black)) , textTheme: TextTheme(title: TextStyle(color: Colors.black)),
title: const Text('flutter_boost_example'),
title: Text('flutter_boost_example'),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
child:Container( child: Container(
margin: const EdgeInsets.all(24.0), margin: const EdgeInsets.all(24.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Container( Container(
margin: const EdgeInsets.only(top: 10.0,bottom: 20.0), margin: const EdgeInsets.only(top: 10.0, bottom: 20.0),
child: Text( child: Text(
message ?? "This is a flutter activity \n params:${widget.params}", message ??
'This is a flutter activity \n params:${widget.params}',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
), ),
// Expanded(child: Container()),
const CupertinoTextField( const CupertinoTextField(
prefix: Icon( prefix: Icon(
CupertinoIcons.person_solid, CupertinoIcons.person_solid,
...@@ -155,7 +157,10 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -155,7 +157,10 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
textCapitalization: TextCapitalization.words, textCapitalization: TextCapitalization.words,
autocorrect: false, autocorrect: false,
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border(bottom: BorderSide(width: 0.0, color: CupertinoColors.inactiveGray)), border: Border(
bottom: BorderSide(
width: 0.0, color: CupertinoColors.inactiveGray),
),
), ),
placeholder: 'Name', placeholder: 'Name',
), ),
...@@ -167,14 +172,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -167,14 +172,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
child: Text( child: Text(
'open native page', 'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("sample://nativePage", urlParams: <dynamic,dynamic>{ 'sample://nativePage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'},
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -184,14 +192,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -184,14 +192,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
child: Text( child: Text(
'open first', 'open first',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("first", urlParams: <dynamic,dynamic>{ 'first',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'},
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -201,14 +212,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -201,14 +212,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
child: Text( child: Text(
'open second', 'open second',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("second", urlParams: <dynamic,dynamic>{ 'second',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'},
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -218,14 +232,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -218,14 +232,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
child: Text( child: Text(
'open tab', 'open tab',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("tab", urlParams: <dynamic,dynamic>{ 'tab',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -235,14 +252,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -235,14 +252,17 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
child: Text( child: Text(
'open flutter page', 'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("sample://flutterPage", urlParams:<dynamic,dynamic> { 'sample://flutterPage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -254,11 +274,12 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -254,11 +274,12 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () { onTap: () {
Navigator.push<dynamic>(context, Navigator.push<dynamic>(
MaterialPageRoute<dynamic>(builder: (_) => PushWidget())); context,
MaterialPageRoute<dynamic>(builder: (_) => PushWidget()),
);
}, },
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
...@@ -268,8 +289,7 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -268,8 +289,7 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
'push Platform demo', 'push Platform demo',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () { onTap: () {},
},
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -280,12 +300,11 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -280,12 +300,11 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => FlutterBoost.singleton onTap: () =>
.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
), ),
], ],
), ),
), ),
), ),
); );
...@@ -293,15 +312,15 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -293,15 +312,15 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
} }
class FragmentRouteWidget extends StatelessWidget { class FragmentRouteWidget extends StatelessWidget {
final Map params; const FragmentRouteWidget(this.params);
FragmentRouteWidget(this.params); final Map<String, dynamic> params;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('flutter_boost_example'), title: const Text('flutter_boost_example'),
), ),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -309,7 +328,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -309,7 +328,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 80.0), margin: const EdgeInsets.only(top: 80.0),
child: Text( child: Text(
"This is a flutter fragment", 'This is a flutter fragment',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -317,7 +336,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -317,7 +336,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 32.0), margin: const EdgeInsets.only(top: 32.0),
child: Text( child: Text(
params['tag'] ?? '', '${params['tag']}' ?? '',
style: TextStyle(fontSize: 28.0, color: Colors.red), style: TextStyle(fontSize: 28.0, color: Colors.red),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -332,7 +351,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -332,7 +351,7 @@ class FragmentRouteWidget extends StatelessWidget {
'open native page', 'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => FlutterBoost.singleton.open("sample://nativePage"), onTap: () => FlutterBoost.singleton.open('sample://nativePage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -343,7 +362,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -343,7 +362,7 @@ class FragmentRouteWidget extends StatelessWidget {
'open flutter page', 'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => FlutterBoost.singleton.open("sample://flutterPage"), onTap: () => FlutterBoost.singleton.open('sample://flutterPage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -355,7 +374,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -355,7 +374,7 @@ class FragmentRouteWidget extends StatelessWidget {
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => onTap: () =>
FlutterBoost.singleton.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
) )
], ],
), ),
...@@ -373,13 +392,13 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -373,13 +392,13 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
void initState() { void initState() {
// TODO: implement initState // TODO(unknown): implement initState
super.initState(); super.initState();
} }
@override @override
void didChangeDependencies() { void didChangeDependencies() {
// TODO: implement didChangeDependencies // TODO(unknown): implement didChangeDependencies
super.didChangeDependencies(); super.didChangeDependencies();
// if (_backPressedListenerUnsub == null) { // if (_backPressedListenerUnsub == null) {
...@@ -395,13 +414,13 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -395,13 +414,13 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
void dispose() { void dispose() {
// TODO: implement dispose // TODO(unknown): implement dispose
super.dispose(); super.dispose();
_backPressedListenerUnsub?.call(); _backPressedListenerUnsub?.call();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FlutterRouteWidget(message: "Pushed Widget"); return const FlutterRouteWidget(message: 'Pushed Widget');
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment