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));
}
}
...@@ -23,8 +23,22 @@ ...@@ -23,8 +23,22 @@
PlatformRouterImp *router = [PlatformRouterImp new]; PlatformRouterImp *router = [PlatformRouterImp new];
[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;
...@@ -48,4 +48,4 @@ class TextViewController { ...@@ -48,4 +48,4 @@ class TextViewController {
assert(text != null); assert(text != null);
return _channel.invokeMethod('setText', text); return _channel.invokeMethod('setText', text);
} }
} }
\ No newline at end of file
This diff is collapsed.
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,95 +21,82 @@ class _TestPageState extends State<TestPage> { ...@@ -18,95 +21,82 @@ 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),
alignment: Alignment.center,
), ),
margin: const EdgeInsets.all(8.0), Container(
alignment: Alignment.center, child: Text(
), '$_counter',
Container( style: Theme.of(context).textTheme.display1,
child: Text( ),
'$_counter', margin: const EdgeInsets.all(8.0),
style: Theme.of(context).textTheme.display1, alignment: Alignment.center,
), ),
margin: const EdgeInsets.all(8.0), Container(
alignment: Alignment.center, child: const TextField(minLines: 2, maxLines: 10),
), padding: const EdgeInsets.all(8.0),
Container(
child: TextField(
minLines: 2,
maxLines: 10,
), ),
padding: const EdgeInsets.all(8.0), TestTextField(),
), Container(
TestTextField(), child: Container(
Container( color: Colors.red,
child: Container( width: double.infinity,
color: Colors.red, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: Container(
Container( color: Colors.orange,
child: Container( width: double.infinity,
color: Colors.orange, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: Container(
Container( color: Colors.green,
child: Container( width: double.infinity,
color: Colors.green, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: Container(
Container( color: Colors.blue,
child: Container( width: double.infinity,
color: Colors.blue, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: Container(
Container( color: Colors.yellow,
child: Container( width: double.infinity,
color: Colors.yellow, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: const TextField(minLines: 2, maxLines: 10),
Container( padding: const EdgeInsets.all(8.0),
child: TextField(
minLines: 2,
maxLines: 10,
), ),
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();
}, },
}); });
} }
...@@ -34,12 +39,17 @@ class _MyAppState extends State<MyApp> { ...@@ -34,12 +39,17 @@ class _MyAppState extends State<MyApp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
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> _,
) {}
} }
This diff is collapsed.
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,100 +21,87 @@ class _TestPageState extends State<TestPage> { ...@@ -18,100 +21,87 @@ 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),
alignment: Alignment.center,
), ),
margin: const EdgeInsets.all(8.0), Container(
alignment: Alignment.center, child: Text(
), '$_counter',
Container( style: Theme.of(context).textTheme.display1,
child: Text( ),
'$_counter', margin: const EdgeInsets.all(8.0),
style: Theme.of(context).textTheme.display1, alignment: Alignment.center,
), ),
margin: const EdgeInsets.all(8.0), Container(
alignment: Alignment.center, child: const TextField(minLines: 2, maxLines: 10),
), padding: const EdgeInsets.all(8.0),
Container(
child: TextField(
minLines: 2,
maxLines: 10,
), ),
padding: const EdgeInsets.all(8.0), TestTextField(),
), Container(
TestTextField(), child: Container(
Container( color: Colors.red,
child: Container( width: double.infinity,
color: Colors.red, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: Container(
Container( color: Colors.orange,
child: Container( width: double.infinity,
color: Colors.orange, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: Container(
Container( color: Colors.green,
child: Container( width: double.infinity,
color: Colors.green, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: Container(
Container( color: Colors.blue,
child: Container( width: double.infinity,
color: Colors.blue, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: Container(
Container( color: Colors.yellow,
child: Container( width: double.infinity,
color: Colors.yellow, height: 128.0,
width: double.infinity, ),
height: 128.0, padding: const EdgeInsets.all(8.0),
), ),
padding: const EdgeInsets.all(8.0), Container(
), child: const TextField(minLines: 2, maxLines: 10),
Container( padding: const EdgeInsets.all(8.0),
child: TextField(
minLines: 2,
maxLines: 10,
), ),
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( this.settings = const BoostContainerSettings(),
{GlobalKey<BoostContainerState> key, String initialRoute,
this.settings = const BoostContainerSettings(), RouteFactory onGenerateRoute,
String initialRoute, RouteFactory onUnknownRoute,
RouteFactory onGenerateRoute, List<NavigatorObserver> observers,
RouteFactory onUnknownRoute, }) : super(
List<NavigatorObserver> observers}) key: key,
: super( initialRoute: initialRoute,
key: key, onGenerateRoute: onGenerateRoute,
initialRoute: initialRoute, onUnknownRoute: onUnknownRoute,
onGenerateRoute: onGenerateRoute, observers: observers,
onUnknownRoute: onUnknownRoute, );
observers: observers);
factory BoostContainer.copy(
factory BoostContainer.copy(Navigator navigator, Navigator navigator, [
[BoostContainerSettings settings = const BoostContainerSettings()]) => BoostContainerSettings settings = const BoostContainerSettings(),
]) =>
BoostContainer( BoostContainer(
key: GlobalKey<BoostContainerState>(), key: GlobalKey<BoostContainerState>(),
settings: settings, settings: settings,
...@@ -69,28 +73,34 @@ class BoostContainer extends Navigator { ...@@ -69,28 +73,34 @@ 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,
onGenerateRoute: (RouteSettings routeSettings) { onGenerateRoute: (RouteSettings routeSettings) {
if (routeSettings.name == '/') { if (routeSettings.name == '/') {
return BoostPageRoute<dynamic>( return BoostPageRoute<dynamic>(
pageName: settings.name, pageName: settings.name,
params: settings.params, params: settings.params,
uniqueId: settings.uniqueId, uniqueId: settings.uniqueId,
animated: false, animated: false,
settings: routeSettings, settings: routeSettings,
builder: settings.builder); builder: settings.builder,
} else { );
return navigator.onGenerateRoute(routeSettings); } else {
} return navigator.onGenerateRoute(routeSettings);
}, }
observers: <NavigatorObserver>[ },
ContainerNavigatorObserver.bindContainerManager(), observers: <NavigatorObserver>[
HeroController(), ContainerNavigatorObserver.bindContainerManager(),
], 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) {
...@@ -199,7 +204,7 @@ class BoostContainerState extends NavigatorState { ...@@ -199,7 +204,7 @@ class BoostContainerState extends NavigatorState {
} }
if (canPop()) { if (canPop()) {
super.pop<T>(result); super.pop<T>(result);
} else { } else {
if (T is Map<String, dynamic>) { if (T is Map<String, dynamic>) {
FlutterBoost.singleton FlutterBoost.singleton
...@@ -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) { (
if (settings.uniqueId == uniqueId) { ContainerLifeCycle state,
observer(state, settings); BoostContainerSettings settings,
} ) {
}); if (settings.uniqueId == uniqueId) {
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>();
BoostPageRoute( final Set<VoidCallback> backPressedListeners = <VoidCallback>{};
{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);
......
This diff is collapsed.
...@@ -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);
} }
...@@ -294,32 +300,34 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -294,32 +300,34 @@ class ContainerManagerState extends State<BoostContainerManager> {
pop(); pop();
} 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();
...@@ -89,10 +110,11 @@ class FlutterBoost { ...@@ -89,10 +110,11 @@ class FlutterBoost {
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(
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,40 +14,42 @@ class MockBoostChannel extends BoostChannel implements Mock { ...@@ -17,40 +14,42 @@ 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);
} }
} }
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);
} }
}); });
} }
This diff is collapsed.
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);
}); });
} }
This diff is collapsed.
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