Commit 9fb145a1 authored by nightfallsad's avatar nightfallsad Committed by GitHub

Merge pull request #7 from alibaba/master

merge code
parents 16f497e9 db7ca34a
...@@ -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
...@@ -22,7 +22,7 @@ rootProject.allprojects { ...@@ -22,7 +22,7 @@ rootProject.allprojects {
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
android { android {
compileSdkVersion 28 compileSdkVersion 29
buildToolsVersion '28.0.3' buildToolsVersion '28.0.3'
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
......
package com.idlefish.flutterboost;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.view.HapticFeedbackConstants;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.Window;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
public class XPlatformPlugin {
public static final int DEFAULT_SYSTEM_UI = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
private Activity activity;
private PlatformChannel platformChannel;
private PlatformChannel.SystemChromeStyle currentTheme;
private int mEnabledOverlays;
private PlatformChannel.PlatformMessageHandler mPlatformMessageHandler = new PlatformChannel.PlatformMessageHandler() {
@Override
public void playSystemSound(@NonNull PlatformChannel.SoundType soundType) {
XPlatformPlugin.this.playSystemSound(soundType);
}
@Override
public void vibrateHapticFeedback(@NonNull PlatformChannel.HapticFeedbackType feedbackType) {
XPlatformPlugin.this.vibrateHapticFeedback(feedbackType);
}
@Override
public void setPreferredOrientations(int androidOrientation) {
setSystemChromePreferredOrientations(androidOrientation);
}
@Override
public void setApplicationSwitcherDescription(@NonNull PlatformChannel.AppSwitcherDescription description) {
setSystemChromeApplicationSwitcherDescription(description);
}
@Override
public void showSystemOverlays(@NonNull List<PlatformChannel.SystemUiOverlay> overlays) {
setSystemChromeEnabledSystemUIOverlays(overlays);
}
@Override
public void restoreSystemUiOverlays() {
restoreSystemChromeSystemUIOverlays();
}
@Override
public void setSystemUiOverlayStyle(@NonNull PlatformChannel.SystemChromeStyle systemUiOverlayStyle) {
setSystemChromeSystemUIOverlayStyle(systemUiOverlayStyle);
}
@Override
public void popSystemNavigator() {
XPlatformPlugin.this.popSystemNavigator();
}
@Override
public CharSequence getClipboardData(@Nullable PlatformChannel.ClipboardContentFormat format) {
return XPlatformPlugin.this.getClipboardData(format);
}
@Override
public void setClipboardData(@NonNull String text) {
XPlatformPlugin.this.setClipboardData(text);
}
@Override
public List<Rect> getSystemGestureExclusionRects() {
return XPlatformPlugin.this.getSystemGestureExclusionRects();
}
@Override
public void setSystemGestureExclusionRects(@NonNull ArrayList<Rect> rects) {
XPlatformPlugin.this.setSystemGestureExclusionRects(rects);
}
};
public XPlatformPlugin( PlatformChannel platformChannel) {
this.platformChannel = platformChannel;
mEnabledOverlays = DEFAULT_SYSTEM_UI;
}
public void attachToActivity(Activity activity ){
this.activity = activity;
this.platformChannel.setPlatformMessageHandler(mPlatformMessageHandler);
}
/**
* Releases all resources held by this {@code PlatformPlugin}.
* <p>
* Do not invoke any methods on a {@code PlatformPlugin} after invoking this method.
*/
public void detachActivity() {
this.activity=null;
this.mPlatformMessageHandler=null;
}
private void playSystemSound(PlatformChannel.SoundType soundType) {
if (soundType == PlatformChannel.SoundType.CLICK) {
View view = activity.getWindow().getDecorView();
view.playSoundEffect(SoundEffectConstants.CLICK);
}
}
private void vibrateHapticFeedback(PlatformChannel.HapticFeedbackType feedbackType) {
View view = activity.getWindow().getDecorView();
switch (feedbackType) {
case STANDARD:
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
break;
case LIGHT_IMPACT:
view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
break;
case MEDIUM_IMPACT:
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
break;
case HEAVY_IMPACT:
// HapticFeedbackConstants.CONTEXT_CLICK from API level 23.
view.performHapticFeedback(6);
break;
case SELECTION_CLICK:
view.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
break;
}
}
private void setSystemChromePreferredOrientations(int androidOrientation) {
activity.setRequestedOrientation(androidOrientation);
}
@SuppressWarnings("deprecation")
private void setSystemChromeApplicationSwitcherDescription(PlatformChannel.AppSwitcherDescription description) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
// Linter refuses to believe we're only executing this code in API 28 unless we use distinct if blocks and
// hardcode the API 28 constant.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P && Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
activity.setTaskDescription(new ActivityManager.TaskDescription(description.label, /*icon=*/ null, description.color));
}
if (Build.VERSION.SDK_INT >= 28) {
ActivityManager.TaskDescription taskDescription = new ActivityManager.TaskDescription(description.label, 0, description.color);
activity.setTaskDescription(taskDescription);
}
}
private void setSystemChromeEnabledSystemUIOverlays(List<PlatformChannel.SystemUiOverlay> overlaysToShow) {
// Start by assuming we want to hide all system overlays (like an immersive game).
int enabledOverlays = DEFAULT_SYSTEM_UI
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
if (overlaysToShow.size() == 0) {
enabledOverlays |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
// Re-add any desired system overlays.
for (int i = 0; i < overlaysToShow.size(); ++i) {
PlatformChannel.SystemUiOverlay overlayToShow = overlaysToShow.get(i);
switch (overlayToShow) {
case TOP_OVERLAYS:
enabledOverlays &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
break;
case BOTTOM_OVERLAYS:
enabledOverlays &= ~View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
enabledOverlays &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
break;
}
}
mEnabledOverlays = enabledOverlays;
updateSystemUiOverlays();
}
/**
* Refreshes Android's window system UI (AKA system chrome) to match Flutter's desired
* {@link PlatformChannel.SystemChromeStyle}.
* <p>
* Updating the system UI Overlays is accomplished by altering the decor view of the
* {@link Window} associated with the {@link Activity} that was provided to this
* {@code PlatformPlugin}.
*/
public void updateSystemUiOverlays(){
activity.getWindow().getDecorView().setSystemUiVisibility(mEnabledOverlays);
if (currentTheme != null) {
setSystemChromeSystemUIOverlayStyle(currentTheme);
}
}
private void restoreSystemChromeSystemUIOverlays() {
updateSystemUiOverlays();
}
private void setSystemChromeSystemUIOverlayStyle(PlatformChannel.SystemChromeStyle systemChromeStyle) {
Window window = activity.getWindow();
View view = window.getDecorView();
int flags = view.getSystemUiVisibility();
// You can change the navigation bar color (including translucent colors)
// in Android, but you can't change the color of the navigation buttons until Android O.
// LIGHT vs DARK effectively isn't supported until then.
// Build.VERSION_CODES.O
if (Build.VERSION.SDK_INT >= 26) {
if (systemChromeStyle.systemNavigationBarIconBrightness != null) {
switch (systemChromeStyle.systemNavigationBarIconBrightness) {
case DARK:
//View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
flags |= 0x10;
break;
case LIGHT:
flags &= ~0x10;
break;
}
}
if (systemChromeStyle.systemNavigationBarColor != null) {
window.setNavigationBarColor(systemChromeStyle.systemNavigationBarColor);
}
}
// Build.VERSION_CODES.M
if (Build.VERSION.SDK_INT >= 23) {
if (systemChromeStyle.statusBarIconBrightness != null) {
switch (systemChromeStyle.statusBarIconBrightness) {
case DARK:
// View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
flags |= 0x2000;
break;
case LIGHT:
flags &= ~0x2000;
break;
}
}
if (systemChromeStyle.statusBarColor != null) {
window.setStatusBarColor(systemChromeStyle.statusBarColor);
}
}
if (systemChromeStyle.systemNavigationBarDividerColor != null) {
// Not available until Android P.
// window.setNavigationBarDividerColor(systemNavigationBarDividerColor);
}
view.setSystemUiVisibility(flags);
currentTheme = systemChromeStyle;
}
private void popSystemNavigator() {
activity.finish();
}
private CharSequence getClipboardData(PlatformChannel.ClipboardContentFormat format) {
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = clipboard.getPrimaryClip();
if (clip == null)
return null;
if (format == null || format == PlatformChannel.ClipboardContentFormat.PLAIN_TEXT) {
return clip.getItemAt(0).coerceToText(activity);
}
return null;
}
private void setClipboardData(String text) {
ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("text label?", text);
clipboard.setPrimaryClip(clip);
}
private List<Rect> getSystemGestureExclusionRects() {
if (Build.VERSION.SDK_INT >= 29) {
Window window = activity.getWindow();
View view = window.getDecorView();
return view.getSystemGestureExclusionRects();
}
return null;
}
private void setSystemGestureExclusionRects(ArrayList<Rect> rects) {
if (Build.VERSION.SDK_INT < 29) {
return;
}
Window window = activity.getWindow();
View view = window.getDecorView();
view.setSystemGestureExclusionRects(rects);
}
}
...@@ -21,6 +21,7 @@ import android.view.*; ...@@ -21,6 +21,7 @@ import android.view.*;
import android.widget.*; import android.widget.*;
import com.idlefish.flutterboost.FlutterBoost; import com.idlefish.flutterboost.FlutterBoost;
import com.idlefish.flutterboost.XFlutterView; import com.idlefish.flutterboost.XFlutterView;
import com.idlefish.flutterboost.XPlatformPlugin;
import io.flutter.Log; import io.flutter.Log;
import io.flutter.embedding.android.DrawableSplashScreen; import io.flutter.embedding.android.DrawableSplashScreen;
import io.flutter.embedding.android.FlutterView; import io.flutter.embedding.android.FlutterView;
...@@ -439,12 +440,8 @@ public class BoostFlutterActivity extends Activity ...@@ -439,12 +440,8 @@ public class BoostFlutterActivity extends Activity
@Nullable @Nullable
@Override @Override
public PlatformPlugin providePlatformPlugin(@Nullable Activity activity, @NonNull FlutterEngine flutterEngine) { public XPlatformPlugin providePlatformPlugin( @NonNull FlutterEngine flutterEngine) {
if (activity != null) { return new XPlatformPlugin( flutterEngine.getPlatformChannel());
return new PlatformPlugin(getActivity(), flutterEngine.getPlatformChannel());
} else {
return null;
}
} }
/** /**
......
...@@ -23,6 +23,7 @@ import java.util.Map; ...@@ -23,6 +23,7 @@ import java.util.Map;
import com.idlefish.flutterboost.FlutterBoost; import com.idlefish.flutterboost.FlutterBoost;
import com.idlefish.flutterboost.Utils; import com.idlefish.flutterboost.Utils;
import com.idlefish.flutterboost.XFlutterView; import com.idlefish.flutterboost.XFlutterView;
import com.idlefish.flutterboost.XPlatformPlugin;
import com.idlefish.flutterboost.interfaces.IFlutterViewContainer; import com.idlefish.flutterboost.interfaces.IFlutterViewContainer;
import com.idlefish.flutterboost.interfaces.IOperateSyncer; import com.idlefish.flutterboost.interfaces.IOperateSyncer;
import io.flutter.Log; import io.flutter.Log;
...@@ -30,6 +31,7 @@ import io.flutter.app.FlutterActivity; ...@@ -30,6 +31,7 @@ import io.flutter.app.FlutterActivity;
import io.flutter.embedding.android.*; import io.flutter.embedding.android.*;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs; import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.platform.PlatformPlugin; import io.flutter.plugin.platform.PlatformPlugin;
...@@ -39,7 +41,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -39,7 +41,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
private static final String TAG = "FlutterActivityAndFragmentDelegate"; private static final String TAG = "FlutterActivityAndFragmentDelegate";
private static int ACTIVITY_CONTROL_SURFACE_ATTACH_TO_ACTVITY_HASH_CODE=0;
@NonNull @NonNull
private Host host; private Host host;
@Nullable @Nullable
...@@ -49,7 +51,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -49,7 +51,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
@Nullable @Nullable
private XFlutterView flutterView; private XFlutterView flutterView;
@Nullable @Nullable
private PlatformPlugin platformPlugin; private XPlatformPlugin platformPlugin;
private boolean isFlutterEngineFromHost; private boolean isFlutterEngineFromHost;
...@@ -95,7 +97,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -95,7 +97,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
// TODO(mattcarroll): the PlatformPlugin needs to be reimagined because it implicitly takes // TODO(mattcarroll): the PlatformPlugin needs to be reimagined because it implicitly takes
// control of the entire window. This is unacceptable for non-fullscreen // control of the entire window. This is unacceptable for non-fullscreen
// use-cases. // use-cases.
platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine); platformPlugin = host.providePlatformPlugin(flutterEngine);
host.configureFlutterEngine(flutterEngine); host.configureFlutterEngine(flutterEngine);
...@@ -129,13 +131,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -129,13 +131,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
Log.v(TAG, "Creating FlutterView."); Log.v(TAG, "Creating FlutterView.");
flutterEngine.getActivityControlSurface().attachToActivity(
host.getActivity(),
host.getLifecycle()
);
mSyncer = FlutterBoost.instance().containerManager().generateSyncer(this); mSyncer = FlutterBoost.instance().containerManager().generateSyncer(this);
ensureAlive(); ensureAlive();
...@@ -176,13 +171,19 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -176,13 +171,19 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
Log.v(TAG, "onResume()"); Log.v(TAG, "onResume()");
ensureAlive(); ensureAlive();
flutterEngine.getLifecycleChannel().appIsResumed(); flutterEngine.getLifecycleChannel().appIsResumed();
if(ACTIVITY_CONTROL_SURFACE_ATTACH_TO_ACTVITY_HASH_CODE==0||
flutterEngine.getActivityControlSurface().attachToActivity( ACTIVITY_CONTROL_SURFACE_ATTACH_TO_ACTVITY_HASH_CODE!=this.host.getActivity().hashCode()){
host.getActivity(), flutterEngine.getActivityControlSurface().detachFromActivityForConfigChanges();
host.getLifecycle() flutterEngine.getActivityControlSurface().attachToActivity(
); host.getActivity(),
host.getLifecycle()
);
ACTIVITY_CONTROL_SURFACE_ATTACH_TO_ACTVITY_HASH_CODE=this.host.getActivity().hashCode();
}
if(platformPlugin!=null)
platformPlugin.attachToActivity( host.getActivity());
} }
...@@ -191,7 +192,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -191,7 +192,6 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
public void onPostResume() { public void onPostResume() {
Log.v(TAG, "onPostResume()"); Log.v(TAG, "onPostResume()");
ensureAlive(); ensureAlive();
// Utils.setStatusBarLightMode(host.getActivity(), true);
} }
...@@ -230,10 +230,15 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -230,10 +230,15 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
// Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment, // Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment,
// and this Fragment's Activity. // and this Fragment's Activity.
if (platformPlugin != null) { if (platformPlugin != null) {
// platformPlugin.destroy(); platformPlugin.detachActivity();
platformPlugin = null; platformPlugin = null;
} }
if(ACTIVITY_CONTROL_SURFACE_ATTACH_TO_ACTVITY_HASH_CODE!=0||
ACTIVITY_CONTROL_SURFACE_ATTACH_TO_ACTVITY_HASH_CODE==this.host.getActivity().hashCode()){
flutterEngine.getActivityControlSurface().detachFromActivityForConfigChanges();
}
Utils.fixInputMethodManagerLeak(host.getActivity()); Utils.fixInputMethodManagerLeak(host.getActivity());
} }
...@@ -461,7 +466,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer ...@@ -461,7 +466,7 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContainer
* Flutter experience should control system chrome. * Flutter experience should control system chrome.
*/ */
@Nullable @Nullable
PlatformPlugin providePlatformPlugin(@Nullable Activity activity, @NonNull FlutterEngine flutterEngine); XPlatformPlugin providePlatformPlugin( @NonNull FlutterEngine flutterEngine);
/** /**
* Hook for the host to configure the {@link FlutterEngine} as desired. * Hook for the host to configure the {@link FlutterEngine} as desired.
......
...@@ -16,6 +16,7 @@ import androidx.fragment.app.FragmentActivity; ...@@ -16,6 +16,7 @@ import androidx.fragment.app.FragmentActivity;
import com.idlefish.flutterboost.FlutterBoost; import com.idlefish.flutterboost.FlutterBoost;
import com.idlefish.flutterboost.Utils; import com.idlefish.flutterboost.Utils;
import com.idlefish.flutterboost.XFlutterView; import com.idlefish.flutterboost.XFlutterView;
import com.idlefish.flutterboost.XPlatformPlugin;
import io.flutter.embedding.android.*; import io.flutter.embedding.android.*;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterShellArgs; import io.flutter.embedding.engine.FlutterShellArgs;
...@@ -467,12 +468,9 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm ...@@ -467,12 +468,9 @@ public class FlutterFragment extends Fragment implements FlutterActivityAndFragm
@Nullable @Nullable
@Override @Override
public PlatformPlugin providePlatformPlugin(@Nullable Activity activity, @NonNull FlutterEngine flutterEngine) { public XPlatformPlugin providePlatformPlugin( @NonNull FlutterEngine flutterEngine) {
if (activity != null) { return new XPlatformPlugin(flutterEngine.getPlatformChannel());
return new PlatformPlugin(getActivity(), flutterEngine.getPlatformChannel());
} else {
return null;
}
} }
/** /**
......
...@@ -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
...@@ -5,11 +5,10 @@ import 'package:flutter_boost_example/platform_view.dart'; ...@@ -5,11 +5,10 @@ import 'package:flutter_boost_example/platform_view.dart';
class FirstRouteWidget extends StatefulWidget { class FirstRouteWidget extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() => _FirstRouteWidgetState();
return new _FirstRouteWidgetState();
}
} }
class _FirstRouteWidgetState extends State<FirstRouteWidget>{
class _FirstRouteWidgetState extends State<FirstRouteWidget> {
_FirstRouteWidgetState(); _FirstRouteWidgetState();
@override @override
...@@ -45,80 +44,86 @@ class _FirstRouteWidgetState extends State<FirstRouteWidget>{ ...@@ -45,80 +44,86 @@ class _FirstRouteWidgetState extends State<FirstRouteWidget>{
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('First Route')),
title: Text('First Route'),
),
body: Center( body: Center(
child: child: Column(
Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: children: <Widget>[
<Widget>[
RaisedButton( RaisedButton(
child: Text('Open native page'), child: const Text('Open native page'),
onPressed: () { onPressed: () {
print("open natve page!"); print('open natve page!');
FlutterBoost.singleton.open("native").then((Map value) { FlutterBoost.singleton
print( .open('native')
"call me when page is finished. did recieve native route result $value"); .then((Map<String, dynamic> value) {
}); print(
}, 'call me when page is finished. did recieve native route result $value');
), });
RaisedButton( },
child: Text('Open FF route'), ),
onPressed: () { RaisedButton(
print("open FF page!"); child: const Text('Open FF route'),
FlutterBoost.singleton.open("firstFirst").then((Map value) { onPressed: () {
print( print('open FF page!');
"call me when page is finished. did recieve FF route result $value"); FlutterBoost.singleton
}); .open('firstFirst')
}, .then((Map<String, dynamic> value) {
), print(
RaisedButton( 'call me when page is finished. did recieve FF route result $value');
child: Text('Open second route1'), });
onPressed: () { },
print("open second page!"); ),
FlutterBoost.singleton.open("second").then((Map value) { RaisedButton(
print( child: const Text('Open second route1'),
"call me when page is finished. did recieve second route result $value"); onPressed: () {
}); print('open second page!');
}, FlutterBoost.singleton
), .open('second')
.then((Map<String, dynamic> value) {
RaisedButton( print(
child: Text('Present second stateful route'), 'call me when page is finished. did recieve second route result $value');
onPressed: () { });
print("Present second stateful page!"); },
FlutterBoost.singleton.open("secondStateful",urlParams:<dynamic,dynamic>{"present":true}).then((Map value) { ),
print( RaisedButton(
"call me when page is finished. did recieve second stateful route result $value"); child: const Text('Present second stateful route'),
}); onPressed: () {
}, print('Present second stateful page!');
), FlutterBoost.singleton.open('secondStateful',
RaisedButton( urlParams: <String, dynamic>{
child: Text('Present second route'), 'present': true
onPressed: () { }).then((Map<String, dynamic> value) {
print("Present second page!"); print(
FlutterBoost.singleton.open("second",urlParams:<dynamic,dynamic>{"present":true}).then((Map value) { 'call me when page is finished. did recieve second stateful route result $value');
print( });
"call me when page is finished. did recieve second route result $value"); },
}); ),
}, RaisedButton(
), child: const Text('Present second route'),
], onPressed: () {
print('Present second page!');
FlutterBoost.singleton.open('second',
urlParams: <String, dynamic>{
'present': true
}).then((Map<String, dynamic> value) {
print(
'call me when page is finished. did recieve second route result $value');
});
},
),
],
), ),
), ),
); );
} }
} }
class FirstFirstRouteWidget extends StatefulWidget { class FirstFirstRouteWidget extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() => _FirstFirstRouteWidgetState();
return new _FirstFirstRouteWidgetState();
}
} }
class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget> {
_FirstFirstRouteWidgetState(); _FirstFirstRouteWidgetState();
@override @override
...@@ -154,20 +159,18 @@ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{ ...@@ -154,20 +159,18 @@ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('First Route')),
title: Text('First Route'),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: Text('Open first route'), child: const Text('Open first route'),
onPressed: () { onPressed: () {
print('open first page again!');
print("open first page again!"); FlutterBoost.singleton
FlutterBoost.singleton.open("first").then((Map value){ .open('first')
print("did recieve first route result"); .then((Map<String, dynamic> value) {
print("did recieve first route result $value"); print('did recieve first route result');
print('did recieve first route result $value');
}); });
}, },
), ),
), ),
...@@ -175,34 +178,33 @@ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{ ...@@ -175,34 +178,33 @@ class _FirstFirstRouteWidgetState extends State<FirstFirstRouteWidget>{
} }
} }
class EmbededFirstRouteWidget extends StatefulWidget { class EmbeddedFirstRouteWidget extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() => _EmbeddedFirstRouteWidgetState();
// TODO: implement createState
return _EmbededFirstRouteWidgetState();
}
} }
class _EmbededFirstRouteWidgetState extends State<EmbededFirstRouteWidget> { class _EmbeddedFirstRouteWidgetState extends State<EmbeddedFirstRouteWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print('_EmbededFirstRouteWidgetState build called!'); print('_EmbededFirstRouteWidgetState build called!');
return Scaffold( return Scaffold(
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: Text('Open second route2'), child: const Text('Open second route2'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<String, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
), ),
); );
} }
@override @override
void dispose() { void dispose() {
print('[XDEBUG]:_EmbededFirstRouteWidgetState disposing~'); print('[XDEBUG]:_EmbededFirstRouteWidgetState disposing~');
...@@ -212,29 +214,24 @@ class _EmbededFirstRouteWidgetState extends State<EmbededFirstRouteWidget> { ...@@ -212,29 +214,24 @@ class _EmbededFirstRouteWidgetState extends State<EmbededFirstRouteWidget> {
class SecondStatefulRouteWidget extends StatefulWidget { class SecondStatefulRouteWidget extends StatefulWidget {
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() => _SecondStatefulRouteWidgetState();
// TODO: implement createState
return _SecondStatefulRouteWidgetState();
}
} }
class _SecondStatefulRouteWidgetState extends State<SecondStatefulRouteWidget>{
class _SecondStatefulRouteWidgetState extends State<SecondStatefulRouteWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('SecondStateful Route')),
title: Text("SecondStateful Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
// Navigate back to first route when tapped. // Navigate back to first route when tapped.
final BoostContainerSettings settings =
BoostContainerSettings settings =
BoostContainer.of(context).settings; BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId, FlutterBoost.singleton.close(settings.uniqueId,
result: <dynamic,dynamic>{"result": "data from second"}); result: <String, dynamic>{'result': 'data from second'});
}, },
child: Text('Go back with result!'), child: const Text('Go back with result!'),
), ),
), ),
); );
...@@ -251,20 +248,19 @@ class SecondRouteWidget extends StatelessWidget { ...@@ -251,20 +248,19 @@ class SecondRouteWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Second Route')),
title: Text("Second Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
// Navigate back to first route when tapped. // Navigate back to first route when tapped.
final BoostContainerSettings settings =
BoostContainerSettings settings =
BoostContainer.of(context).settings; BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId, FlutterBoost.singleton.close(
result: <dynamic,dynamic>{"result": "data from second"}); settings.uniqueId,
result: <String, dynamic>{'result': 'data from second'},
);
}, },
child: Text('Go back with result!'), child: const Text('Go back with result!'),
), ),
), ),
); );
...@@ -275,15 +271,13 @@ class TabRouteWidget extends StatelessWidget { ...@@ -275,15 +271,13 @@ class TabRouteWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Tab Route')),
title: Text("Tab Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
FlutterBoost.singleton.open("second"); FlutterBoost.singleton.open('second');
}, },
child: Text('Open second route3'), child: const Text('Open second route3'),
), ),
), ),
); );
...@@ -294,17 +288,17 @@ class PlatformRouteWidget extends StatelessWidget { ...@@ -294,17 +288,17 @@ class PlatformRouteWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Platform Route')),
title:Text("Platform Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: TextView(), child: const TextView(),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<String, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -312,9 +306,11 @@ class PlatformRouteWidget extends StatelessWidget { ...@@ -312,9 +306,11 @@ class PlatformRouteWidget extends StatelessWidget {
); );
} }
} }
class FlutterRouteWidget extends StatefulWidget { class FlutterRouteWidget extends StatefulWidget {
FlutterRouteWidget({this.params,this.message}); const FlutterRouteWidget({this.params, this.message});
final Map params;
final Map<String, dynamic> params;
final String message; final String message;
@override @override
...@@ -322,178 +318,199 @@ class FlutterRouteWidget extends StatefulWidget { ...@@ -322,178 +318,199 @@ class FlutterRouteWidget extends StatefulWidget {
} }
class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
final TextEditingController _usernameController = TextEditingController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final String message=widget.message; final String message = widget.message;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
brightness:Brightness.light, brightness: Brightness.light,
backgroundColor: Colors.white, backgroundColor: Colors.white,
textTheme:new TextTheme(title: TextStyle(color: Colors.black)) , textTheme: const TextTheme(title: TextStyle(color: Colors.black)),
title: const Text('flutter_boost_example'),
title: Text('flutter_boost_example'),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
child:Container( child: Container(
margin: const EdgeInsets.all(24.0), margin: const EdgeInsets.all(24.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Container( Container(
margin: const EdgeInsets.only(top: 10.0,bottom: 20.0), margin: const EdgeInsets.only(top: 10.0, bottom: 20.0),
child: Text( child: Text(
message ?? "This is a flutter activity \n params:${widget.params}", message ??
style: TextStyle(fontSize: 28.0, color: Colors.blue), 'This is a flutter activity \n params:${widget.params}',
), style: TextStyle(fontSize: 28.0, color: Colors.blue),
alignment: AlignmentDirectional.center,
), ),
// Expanded(child: Container()), alignment: AlignmentDirectional.center,
const CupertinoTextField( ),
prefix: Icon( const CupertinoTextField(
CupertinoIcons.person_solid, prefix: Icon(
color: CupertinoColors.lightBackgroundGray, CupertinoIcons.person_solid,
size: 28.0, color: CupertinoColors.lightBackgroundGray,
size: 28.0,
),
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 12.0),
clearButtonMode: OverlayVisibilityMode.editing,
textCapitalization: TextCapitalization.words,
autocorrect: false,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 0.0, color: CupertinoColors.inactiveGray),
), ),
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 12.0), ),
clearButtonMode: OverlayVisibilityMode.editing, placeholder: 'Name',
textCapitalization: TextCapitalization.words, ),
autocorrect: false, InkWell(
decoration: BoxDecoration( child: Container(
border: Border(bottom: BorderSide(width: 0.0, color: CupertinoColors.inactiveGray)), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: const Text(
'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black),
), ),
placeholder: 'Name',
), ),
InkWell(
child: Container( /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
padding: const EdgeInsets.all(8.0), /// 例如:sample://nativePage?aaa=bbb
margin: const EdgeInsets.all(8.0), onTap: () => FlutterBoost.singleton.open(
color: Colors.yellow, 'sample://nativePage',
child: Text( urlParams: <String, dynamic>{
'open native page', 'query': <String, dynamic>{'aaa': 'bbb'}
style: TextStyle(fontSize: 22.0, color: Colors.black), },
)), ),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 InkWell(
///例如:sample://nativePage?aaa=bbb child: Container(
onTap: () => FlutterBoost.singleton padding: const EdgeInsets.all(8.0),
.open("sample://nativePage", urlParams: <dynamic,dynamic>{ margin: const EdgeInsets.all(8.0),
"query": {"aaa": "bbb"} color: Colors.yellow,
}), child: const Text(
'open first',
style: TextStyle(fontSize: 22.0, color: Colors.black),
),
), ),
InkWell(
child: Container( /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
padding: const EdgeInsets.all(8.0), /// 例如:sample://nativePage?aaa=bbb
margin: const EdgeInsets.all(8.0), onTap: () => FlutterBoost.singleton.open(
color: Colors.yellow, 'first',
child: Text( urlParams: <String, dynamic>{
'open first', 'query': <String, dynamic>{'aaa': 'bbb'}
style: TextStyle(fontSize: 22.0, color: Colors.black), },
)),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton
.open("first", urlParams: <dynamic,dynamic>{
"query": {"aaa": "bbb"}
}),
), ),
InkWell( ),
child: Container( InkWell(
padding: const EdgeInsets.all(8.0), child: Container(
margin: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
color: Colors.yellow, margin: const EdgeInsets.all(8.0),
child: Text( color: Colors.yellow,
'open second', child: const Text(
style: TextStyle(fontSize: 22.0, color: Colors.black), 'open second',
)), style: TextStyle(fontSize: 22.0, color: Colors.black),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton
.open("second", urlParams:<dynamic,dynamic> {
"query": {"aaa": "bbb"}
}),
), ),
InkWell(
child: Container( /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
padding: const EdgeInsets.all(8.0), /// 例如:sample://nativePage?aaa=bbb
margin: const EdgeInsets.all(8.0), onTap: () => FlutterBoost.singleton.open(
color: Colors.yellow, 'second',
child: Text( urlParams: <String, dynamic>{
'open tab', 'query': <String, dynamic>{'aaa': 'bbb'}
style: TextStyle(fontSize: 22.0, color: Colors.black), },
)),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton
.open("tab", urlParams:<dynamic,dynamic> {
"query": {"aaa": "bbb"}
}),
), ),
InkWell( ),
child: Container( InkWell(
padding: const EdgeInsets.all(8.0), child: Container(
margin: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
color: Colors.yellow, margin: const EdgeInsets.all(8.0),
child: Text( color: Colors.yellow,
'open flutter page', child: const Text(
style: TextStyle(fontSize: 22.0, color: Colors.black), 'open tab',
)), style: TextStyle(fontSize: 22.0, color: Colors.black),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton
.open("sample://flutterPage", urlParams:<String,dynamic> {
"query": {"aaa": "bbb"}
}),
), ),
InkWell(
child: Container( /// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
padding: const EdgeInsets.all(8.0), /// 例如:sample://nativePage?aaa=bbb
margin: const EdgeInsets.all(8.0), onTap: () => FlutterBoost.singleton.open(
color: Colors.yellow, 'tab',
child: Text( urlParams: <String, dynamic>{
'push flutter widget', 'query': <String, dynamic>{'aaa': 'bbb'}
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
onTap: () {
Navigator.push<dynamic>(context,
MaterialPageRoute<dynamic>(builder: (_) => PushWidget()));
}, },
), ),
),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: const Text(
'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black),
),
),
/// 后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
/// 例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton.open(
'sample://flutterPage',
urlParams: <String, dynamic>{
'query': <String, dynamic>{'aaa': 'bbb'}
},
),
),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: const Text(
'push flutter widget',
style: TextStyle(fontSize: 22.0, color: Colors.black),
),
),
onTap: () {
Navigator.push<dynamic>(
context,
MaterialPageRoute<dynamic>(builder: (_) => PushWidget()),
);
},
),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'push Platform demo', 'push Platform demo',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () { onTap: () {
Navigator.push<dynamic>(context, Navigator.push<dynamic>(
MaterialPageRoute<dynamic>(builder: (_) => PlatformRouteWidget())); context,
MaterialPageRoute<dynamic>(
builder: (_) => PlatformRouteWidget()),
);
}, },
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton
.open("sample://flutterFragmentPage"),
), ),
], onTap: () =>
), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
),
],
),
), ),
), ),
); );
...@@ -501,23 +518,21 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -501,23 +518,21 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
} }
class FragmentRouteWidget extends StatelessWidget { class FragmentRouteWidget extends StatelessWidget {
final Map params; const FragmentRouteWidget(this.params);
FragmentRouteWidget(this.params); final Map<String, dynamic> params;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('flutter_boost_example')),
title: Text('flutter_boost_example'),
),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Container( Container(
margin: const EdgeInsets.only(top: 80.0), margin: const EdgeInsets.only(top: 80.0),
child: Text( child: Text(
"This is a flutter fragment", 'This is a flutter fragment',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -525,7 +540,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -525,7 +540,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 32.0), margin: const EdgeInsets.only(top: 32.0),
child: Text( child: Text(
params['tag'] ?? '', '${params['tag']}' ?? '',
style: TextStyle(fontSize: 28.0, color: Colors.red), style: TextStyle(fontSize: 28.0, color: Colors.red),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -533,37 +548,40 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -533,37 +548,40 @@ class FragmentRouteWidget extends StatelessWidget {
Expanded(child: Container()), Expanded(child: Container()),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open native page', 'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton.open("sample://nativePage"), ),
onTap: () => FlutterBoost.singleton.open('sample://nativePage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open flutter page', 'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton.open("sample://flutterPage"), ),
onTap: () => FlutterBoost.singleton.open('sample://flutterPage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 80.0), margin: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 80.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: const Text(
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () => onTap: () =>
FlutterBoost.singleton.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
) )
], ],
), ),
...@@ -579,15 +597,8 @@ class PushWidget extends StatefulWidget { ...@@ -579,15 +597,8 @@ class PushWidget extends StatefulWidget {
class _PushWidgetState extends State<PushWidget> { class _PushWidgetState extends State<PushWidget> {
VoidCallback _backPressedListenerUnsub; VoidCallback _backPressedListenerUnsub;
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override @override
void didChangeDependencies() { void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies(); super.didChangeDependencies();
// if (_backPressedListenerUnsub == null) { // if (_backPressedListenerUnsub == null) {
...@@ -603,7 +614,6 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -603,7 +614,6 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
void dispose() { void dispose() {
// TODO: implement dispose
print('[XDEBUG] - PushWidget is disposing~'); print('[XDEBUG] - PushWidget is disposing~');
super.dispose(); super.dispose();
_backPressedListenerUnsub?.call(); _backPressedListenerUnsub?.call();
...@@ -611,6 +621,6 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -611,6 +621,6 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FlutterRouteWidget(message: "Pushed Widget"); return const FlutterRouteWidget(message: 'Pushed Widget');
} }
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class TestPage extends StatefulWidget { class TestPage extends StatefulWidget {
TestPage({Key key, this.title = "Input Test"}) : super(key: key); const TestPage({
Key key,
this.title = 'Input Test',
}) : super(key: key);
final String title; final String title;
...@@ -18,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> _,
) {}
} }
...@@ -6,15 +6,18 @@ class FirstRouteWidget extends StatelessWidget { ...@@ -6,15 +6,18 @@ class FirstRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('First Route'), title: const Text('First Route'),
), ),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: Text('Open second route'), child: const Text('Open second route'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
print("call me when page is finished. did recieve second route result $value"); .open('second')
.then((Map<String, dynamic> value) {
print(
'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -28,19 +31,21 @@ class SecondRouteWidget extends StatelessWidget { ...@@ -28,19 +31,21 @@ class SecondRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text("Second Route"), title: const Text('Second Route'),
), ),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
// Navigate back to first route when tapped. // Navigate back to first route when tapped.
BoostContainerSettings settings = final BoostContainerSettings settings =
BoostContainer.of(context).settings; BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId, FlutterBoost.singleton.close(
result: <dynamic,dynamic>{"result": "data from second"}); settings.uniqueId,
result: <String, dynamic>{'result': 'data from second'},
);
}, },
child: Text('Go back with result!'), child: const Text('Go back with result!'),
), ),
), ),
); );
...@@ -51,15 +56,13 @@ class TabRouteWidget extends StatelessWidget { ...@@ -51,15 +56,13 @@ class TabRouteWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Tab Route')),
title: Text("Tab Route"),
),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
FlutterBoost.singleton.open("second"); FlutterBoost.singleton.open('second');
}, },
child: Text('Open second route'), child: const Text('Open second route'),
), ),
), ),
); );
...@@ -67,15 +70,15 @@ class TabRouteWidget extends StatelessWidget { ...@@ -67,15 +70,15 @@ class TabRouteWidget extends StatelessWidget {
} }
class FlutterRouteWidget extends StatelessWidget { class FlutterRouteWidget extends StatelessWidget {
final String message; const FlutterRouteWidget({this.message});
FlutterRouteWidget({this.message}); final String message;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('flutter_boost_example'), title: const Text('flutter_boost_example'),
), ),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -83,7 +86,7 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -83,7 +86,7 @@ class FlutterRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 80.0), margin: const EdgeInsets.only(top: 80.0),
child: Text( child: Text(
message ?? "This is a flutter activity", message ?? 'This is a flutter activity',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -101,10 +104,12 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -101,10 +104,12 @@ class FlutterRouteWidget extends StatelessWidget {
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => onTap: () => FlutterBoost.singleton.open(
FlutterBoost.singleton.open("sample://nativePage", urlParams: <dynamic,dynamic>{ 'sample://nativePage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'}
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -118,36 +123,42 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -118,36 +123,42 @@ class FlutterRouteWidget extends StatelessWidget {
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => onTap: () => FlutterBoost.singleton.open(
FlutterBoost.singleton.open("sample://flutterPage", urlParams: <dynamic,dynamic>{ 'sample://flutterPage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'},
},
),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: Text(
'push flutter widget', 'push flutter widget',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () { onTap: () {
Navigator.push<dynamic>( Navigator.push<dynamic>(
context, MaterialPageRoute<dynamic>(builder: (_) => PushWidget())); context,
MaterialPageRoute<dynamic>(builder: (_) => PushWidget()),
);
}, },
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: Text(
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () => onTap: () =>
FlutterBoost.singleton.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
), ),
], ],
), ),
...@@ -156,15 +167,15 @@ class FlutterRouteWidget extends StatelessWidget { ...@@ -156,15 +167,15 @@ class FlutterRouteWidget extends StatelessWidget {
} }
class FragmentRouteWidget extends StatelessWidget { class FragmentRouteWidget extends StatelessWidget {
final Map params; const FragmentRouteWidget(this.params);
FragmentRouteWidget(this.params); final Map<String, dynamic> params;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('flutter_boost_example'), title: const Text('flutter_boost_example'),
), ),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -172,7 +183,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -172,7 +183,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 80.0), margin: const EdgeInsets.only(top: 80.0),
child: Text( child: Text(
"This is a flutter fragment", 'This is a flutter fragment',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -180,7 +191,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -180,7 +191,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 32.0), margin: const EdgeInsets.only(top: 32.0),
child: Text( child: Text(
params['tag'] ?? '', '${params['tag']}' ?? '',
style: TextStyle(fontSize: 28.0, color: Colors.red), style: TextStyle(fontSize: 28.0, color: Colors.red),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -188,37 +199,40 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -188,37 +199,40 @@ class FragmentRouteWidget extends StatelessWidget {
Expanded(child: Container()), Expanded(child: Container()),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: Text(
'open native page', 'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton.open("sample://nativePage"), ),
onTap: () => FlutterBoost.singleton.open('sample://nativePage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: Text(
'open flutter page', 'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
onTap: () => FlutterBoost.singleton.open("sample://flutterPage"), ),
onTap: () => FlutterBoost.singleton.open('sample://flutterPage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 80.0), margin: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 80.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: Text(
'open flutter fragment page', 'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), ),
),
onTap: () => onTap: () =>
FlutterBoost.singleton.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
) )
], ],
), ),
...@@ -234,15 +248,8 @@ class PushWidget extends StatefulWidget { ...@@ -234,15 +248,8 @@ class PushWidget extends StatefulWidget {
class _PushWidgetState extends State<PushWidget> { class _PushWidgetState extends State<PushWidget> {
VoidCallback _backPressedListenerUnsub; VoidCallback _backPressedListenerUnsub;
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override @override
void didChangeDependencies() { void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies(); super.didChangeDependencies();
// if (_backPressedListenerUnsub == null) { // if (_backPressedListenerUnsub == null) {
...@@ -258,13 +265,12 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -258,13 +265,12 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
void dispose() { void dispose() {
// TODO: implement dispose
super.dispose(); super.dispose();
_backPressedListenerUnsub?.call(); _backPressedListenerUnsub?.call();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FlutterRouteWidget(message: "Pushed Widget"); return const FlutterRouteWidget(message: 'Pushed Widget');
} }
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class TestPage extends StatefulWidget { class TestPage extends StatefulWidget {
TestPage({Key key, this.title = "Input Test"}) : super(key: key); const TestPage({
Key key,
this.title = 'Input Test',
}) : super(key: key);
final String title; final String title;
...@@ -18,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);
......
...@@ -27,12 +27,25 @@ import 'dart:io'; ...@@ -27,12 +27,25 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart'; import 'package:flutter/semantics.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import '../channel/boost_channel.dart'; import '../channel/boost_channel.dart';
import 'boost_container.dart';
import '../flutter_boost.dart'; import '../flutter_boost.dart';
import '../support/logger.dart'; import '../support/logger.dart';
import 'boost_container.dart';
class ContainerCoordinator { class ContainerCoordinator {
ContainerCoordinator(BoostChannel channel) : assert(_instance == null) {
_instance = this;
channel
..addEventListener(
'lifecycle',
(String name, Map<String, dynamic> arguments) =>
_onChannelEvent(arguments),
)
..addMethodHandler((MethodCall call) => _onMethodCall(call));
}
static ContainerCoordinator get singleton => _instance; static ContainerCoordinator get singleton => _instance;
static ContainerCoordinator _instance; static ContainerCoordinator _instance;
...@@ -40,19 +53,11 @@ class ContainerCoordinator { ...@@ -40,19 +53,11 @@ class ContainerCoordinator {
final Map<String, PageBuilder> _pageBuilders = <String, PageBuilder>{}; final Map<String, PageBuilder> _pageBuilders = <String, PageBuilder>{};
PageBuilder _defaultPageBuilder; PageBuilder _defaultPageBuilder;
ContainerCoordinator(BoostChannel channel) {
assert(_instance == null);
_instance = this;
channel.addEventListener("lifecycle",
(String name, Map arguments) => _onChannelEvent(arguments));
channel.addMethodHandler((MethodCall call) => _onMethodCall(call));
}
BoostContainerSettings _createContainerSettings( BoostContainerSettings _createContainerSettings(
String name, Map params, String pageId) { String name,
Map<String, dynamic> params,
String pageId,
) {
Widget page; Widget page;
final BoostContainerSettings routeSettings = BoostContainerSettings( final BoostContainerSettings routeSettings = BoostContainerSettings(
...@@ -60,12 +65,12 @@ class ContainerCoordinator { ...@@ -60,12 +65,12 @@ class ContainerCoordinator {
name: name, name: name,
params: params, params: params,
builder: (BuildContext ctx) { builder: (BuildContext ctx) {
//Try to build a page using keyed builder. // Try to build a page using keyed builder.
if (_pageBuilders[name] != null) { if (_pageBuilders[name] != null) {
page = _pageBuilders[name](name, params, pageId); page = _pageBuilders[name](name, params, pageId);
} }
//Build a page using default builder. // Build a page using default builder.
if (page == null && _defaultPageBuilder != null) { if (page == null && _defaultPageBuilder != null) {
page = _defaultPageBuilder(name, params, pageId); page = _defaultPageBuilder(name, params, pageId);
} }
...@@ -79,12 +84,12 @@ class ContainerCoordinator { ...@@ -79,12 +84,12 @@ class ContainerCoordinator {
return routeSettings; return routeSettings;
} }
//Register a default page builder. /// Register a default page builder.
void registerDefaultPageBuilder(PageBuilder builder) { void registerDefaultPageBuilder(PageBuilder builder) {
_defaultPageBuilder = builder; _defaultPageBuilder = builder;
} }
//Register page builder for a key. /// Register page builder for a key.
void registerPageBuilder(String pageName, PageBuilder builder) { void registerPageBuilder(String pageName, PageBuilder builder) {
if (pageName != null && builder != null) { if (pageName != null && builder != null) {
_pageBuilders[pageName] = builder; _pageBuilders[pageName] = builder;
...@@ -98,41 +103,35 @@ class ContainerCoordinator { ...@@ -98,41 +103,35 @@ class ContainerCoordinator {
} }
Future<dynamic> _onChannelEvent(dynamic event) { Future<dynamic> _onChannelEvent(dynamic event) {
if (event is Map) { if (event is Map<String, dynamic>) {
Map map = event; final Map<String, dynamic> map = event;
final String type = map['type']; final String type = map['type'] as String;
Logger.log('onEvent $type'); Logger.log('onEvent $type');
switch (type) { switch (type) {
//Handler back key pressed event. // Handler back key pressed event.
case 'backPressedCallback': case 'backPressedCallback':
{ final String id = map['uniqueId'] as String;
final String id = map['uniqueId']; FlutterBoost.containerManager
FlutterBoost.containerManager ?.containerStateOf(id)
?.containerStateOf(id) ?.performBackPressed();
?.performBackPressed();
}
break; break;
//Enter foregroud // Enter foreground
case 'foreground': case 'foreground':
{ FlutterBoost.containerManager?.setForeground();
FlutterBoost.containerManager?.setForeground();
}
break; break;
//Enter background // Enter background
case 'background': case 'background':
{ FlutterBoost.containerManager?.setBackground();
FlutterBoost.containerManager?.setBackground();
}
break; break;
//Schedule a frame. // Schedule a frame.
case 'scheduleFrame': case 'scheduleFrame':
{ WidgetsBinding.instance.scheduleForcedFrame();
WidgetsBinding.instance.scheduleForcedFrame(); Future<dynamic>.delayed(
Future<dynamic>.delayed(Duration(milliseconds: 250), const Duration(milliseconds: 250),
() => WidgetsBinding.instance.scheduleFrame()); () => WidgetsBinding.instance.scheduleFrame(),
} );
break; break;
} }
} }
...@@ -141,72 +140,52 @@ class ContainerCoordinator { ...@@ -141,72 +140,52 @@ class ContainerCoordinator {
} }
Future<dynamic> _onMethodCall(MethodCall call) { Future<dynamic> _onMethodCall(MethodCall call) {
Logger.log("onMetohdCall ${call.method}"); Logger.log('onMetohdCall ${call.method}');
final String pageName = call.arguments['pageName'] as String;
final Map<String, dynamic> params =
(call.arguments['params'] as Map<dynamic, dynamic>)
?.cast<String, dynamic>();
final String uniqueId = call.arguments['uniqueId'] as String;
switch (call.method) { switch (call.method) {
case "didInitPageContainer": case 'didInitPageContainer':
{ _nativeContainerDidInit(pageName, params, uniqueId);
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerDidInit(pageName, params, uniqueId);
}
break; break;
case "willShowPageContainer": case 'willShowPageContainer':
{ _nativeContainerWillShow(pageName, params, uniqueId);
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerWillShow(pageName, params, uniqueId);
}
break; break;
case "didShowPageContainer": case 'didShowPageContainer':
{ nativeContainerDidShow(pageName, params, uniqueId);
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
nativeContainerDidShow(pageName, params, uniqueId);
}
break; break;
case "willDisappearPageContainer": case 'willDisappearPageContainer':
{ _nativeContainerWillDisappear(pageName, params, uniqueId);
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerWillDisappear(pageName, params, uniqueId);
}
break; break;
case "didDisappearPageContainer": case 'didDisappearPageContainer':
{ _nativeContainerDidDisappear(pageName, params, uniqueId);
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerDidDisappear(pageName, params, uniqueId);
}
break; break;
case "willDeallocPageContainer": case 'willDeallocPageContainer':
{ _nativeContainerWillDealloc(pageName, params, uniqueId);
String pageName = call.arguments["pageName"];
Map params = call.arguments["params"];
String uniqueId = call.arguments["uniqueId"];
_nativeContainerWillDealloc(pageName, params, uniqueId);
}
break; break;
case "onNativePageResult": case 'onNativePageResult':
{}
break; break;
} }
return Future<dynamic>(() {}); return Future<dynamic>(() {});
} }
bool _nativeContainerWillShow(String name, Map params, String pageId) { bool _nativeContainerWillShow(
String name,
Map<String, dynamic> params,
String pageId,
) {
if (FlutterBoost.containerManager?.containsContainer(pageId) != true) { if (FlutterBoost.containerManager?.containsContainer(pageId) != true) {
FlutterBoost.containerManager FlutterBoost.containerManager?.pushContainer(
?.pushContainer(_createContainerSettings(name, params, pageId)); _createContainerSettings(name, params, pageId),
);
} }
//TODO, 需要验证android代码是否也可以移到这里 // TODO(unknown): 需要验证android代码是否也可以移到这里
if (Platform.isIOS) { if (Platform.isIOS) {
try { try {
final SemanticsOwner owner = final SemanticsOwner owner =
...@@ -221,11 +200,15 @@ class ContainerCoordinator { ...@@ -221,11 +200,15 @@ class ContainerCoordinator {
return true; return true;
} }
bool nativeContainerDidShow(String name, Map params, String pageId) { bool nativeContainerDidShow(
String name,
Map<String, dynamic> params,
String pageId,
) {
FlutterBoost.containerManager FlutterBoost.containerManager
?.showContainer(_createContainerSettings(name, params, pageId)); ?.showContainer(_createContainerSettings(name, params, pageId));
//在Android上对无障碍辅助模式的兼容 // Compatible to accessibility mode on Android.
if (Platform.isAndroid) { if (Platform.isAndroid) {
try { try {
final SemanticsOwner owner = final SemanticsOwner owner =
...@@ -238,57 +221,93 @@ class ContainerCoordinator { ...@@ -238,57 +221,93 @@ class ContainerCoordinator {
} }
} }
performContainerLifeCycle(_createContainerSettings(name, params, pageId), performContainerLifeCycle(
ContainerLifeCycle.Appear); _createContainerSettings(name, params, pageId),
ContainerLifeCycle.Appear,
);
Logger.log( Logger.log(
'native containner did show-$name,\nmanager dump:\n${FlutterBoost.containerManager?.dump()}'); 'native containner did show-$name,\n'
'manager dump:\n'
'${FlutterBoost.containerManager?.dump()}',
);
return true; return true;
} }
bool _nativeContainerWillDisappear(String name, Map params, String pageId) { bool _nativeContainerWillDisappear(
performContainerLifeCycle(_createContainerSettings(name, params, pageId), String name,
ContainerLifeCycle.WillDisappear); Map<String, dynamic> params,
String pageId,
) {
performContainerLifeCycle(
_createContainerSettings(name, params, pageId),
ContainerLifeCycle.WillDisappear,
);
return true; return true;
} }
bool _nativeContainerDidDisappear(String name, Map params, String pageId) { bool _nativeContainerDidDisappear(
performContainerLifeCycle(_createContainerSettings(name, params, pageId), String name,
ContainerLifeCycle.Disappear); Map<String, dynamic> params,
String pageId,
) {
performContainerLifeCycle(
_createContainerSettings(name, params, pageId),
ContainerLifeCycle.Disappear,
);
return true; return true;
} }
bool _nativeContainerDidInit(String name, Map params, String pageId) { bool _nativeContainerDidInit(
performContainerLifeCycle(_createContainerSettings(name, params, pageId), String name,
ContainerLifeCycle.Init); Map<String, dynamic> params,
String pageId,
) {
performContainerLifeCycle(
_createContainerSettings(name, params, pageId),
ContainerLifeCycle.Init,
);
return true; return true;
} }
bool _nativeContainerWillDealloc(String name, Map params, String pageId) { bool _nativeContainerWillDealloc(
String name, Map<String, dynamic> params, String pageId) {
try { try {
performContainerLifeCycle(_createContainerSettings(name, params, pageId), performContainerLifeCycle(
ContainerLifeCycle.Destroy); _createContainerSettings(name, params, pageId),
ContainerLifeCycle.Destroy,
);
} catch (e) { } catch (e) {
Logger.log('nativeContainerWillDealloc error: $e'); Logger.log('nativeContainerWillDealloc error: $e');
} }
FlutterBoost.containerManager?.remove(pageId); FlutterBoost.containerManager?.remove(pageId);
Logger.log( Logger.log(
'native containner dealloc for $name, \n manager dump:\n${FlutterBoost.containerManager?.dump()}'); 'native containner dealloc for $name, \n'
'manager dump:\n'
'${FlutterBoost.containerManager?.dump()}',
);
return true; return true;
} }
static void performContainerLifeCycle( static void performContainerLifeCycle(
BoostContainerSettings settings, ContainerLifeCycle lifeCycle) { BoostContainerSettings settings,
for (BoostContainerLifeCycleObserver observer in FlutterBoost ContainerLifeCycle lifeCycle,
) {
final Set<BoostContainerLifeCycleObserver> observers = FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerLifeCycleObserver>()) { .observersOf<BoostContainerLifeCycleObserver>();
for (final BoostContainerLifeCycleObserver observer in observers) {
observer(lifeCycle, settings); observer(lifeCycle, settings);
} }
Logger.log( Logger.log(
'BoostContainerLifeCycleObserver container:${settings.name} lifeCycle:$lifeCycle'); 'BoostContainerLifeCycleObserver'
'container:${settings.name}'
'lifeCycle:$lifeCycle',
);
} }
} }
...@@ -23,10 +23,11 @@ ...@@ -23,10 +23,11 @@
*/ */
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'boost_container.dart';
import 'container_coordinator.dart';
import '../flutter_boost.dart'; import '../flutter_boost.dart';
import '../support/logger.dart'; import '../support/logger.dart';
import 'boost_container.dart';
import 'container_coordinator.dart';
enum ContainerOperation { Push, Onstage, Pop, Remove } enum ContainerOperation { Push, Onstage, Pop, Remove }
...@@ -35,12 +36,16 @@ typedef BoostContainerObserver = void Function( ...@@ -35,12 +36,16 @@ typedef BoostContainerObserver = void Function(
@immutable @immutable
class BoostContainerManager extends StatefulWidget { class BoostContainerManager extends StatefulWidget {
const BoostContainerManager({
Key key,
this.initNavigator,
this.prePushRoute,
this.postPushRoute,
}) : super(key: key);
final Navigator initNavigator; final Navigator initNavigator;
final PrePushRoute prePushRoute; final PrePushRoute prePushRoute;
final PostPushRoute postPushRoute; final PostPushRoute postPushRoute;
const BoostContainerManager(
{Key key, this.initNavigator, this.prePushRoute, this.postPushRoute})
: super(key: key);
@override @override
ContainerManagerState createState() => ContainerManagerState(); ContainerManagerState createState() => ContainerManagerState();
...@@ -76,15 +81,15 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -76,15 +81,15 @@ class ContainerManagerState extends State<BoostContainerManager> {
bool get foreground => _foreground; bool get foreground => _foreground;
//Number of containers. // Number of containers.
int get containerCounts => _offstage.length; int get containerCounts => _offstage.length;
List<BoostContainer> get offstage => _offstage; List<BoostContainer> get offstage => _offstage;
//Setting for current visible container. // Setting for current visible container.
BoostContainerSettings get onstageSettings => _onstage.settings; BoostContainerSettings get onstageSettings => _onstage.settings;
//Current visible container. // Current visible container.
BoostContainerState get onstageContainer => _stateOf(_onstage); BoostContainerState get onstageContainer => _stateOf(_onstage);
BoostContainerState get subContainer => BoostContainerState get subContainer =>
...@@ -118,8 +123,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -118,8 +123,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
} }
BoostContainerState _stateOf(BoostContainer container) { BoostContainerState _stateOf(BoostContainer container) {
if (container.key != null && if (container.key is GlobalKey<BoostContainerState>) {
container.key is GlobalKey<BoostContainerState>) {
final GlobalKey<BoostContainerState> globalKey = final GlobalKey<BoostContainerState> globalKey =
container.key as GlobalKey<BoostContainerState>; container.key as GlobalKey<BoostContainerState>;
return globalKey.currentState; return globalKey.currentState;
...@@ -133,7 +137,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -133,7 +137,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
void _onShownContainerChanged(String old, String now) { void _onShownContainerChanged(String old, String now) {
Logger.log('onShownContainerChanged old:$old now:$now'); Logger.log('onShownContainerChanged old:$old now:$now');
Map<String, dynamic> properties = new Map<String, dynamic>(); final Map<String, dynamic> properties = <String, dynamic>{};
properties['newName'] = now; properties['newName'] = now;
properties['oldName'] = old; properties['oldName'] = old;
...@@ -149,7 +153,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -149,7 +153,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
} }
if (_leastEntries != null && _leastEntries.isNotEmpty) { if (_leastEntries != null && _leastEntries.isNotEmpty) {
for (_ContainerOverlayEntry entry in _leastEntries) { for (final _ContainerOverlayEntry entry in _leastEntries) {
entry.remove(); entry.remove();
} }
} }
...@@ -223,7 +227,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -223,7 +227,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
setState(() {}); setState(() {});
for (BoostContainerObserver observer in FlutterBoost for (final BoostContainerObserver observer in FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerObserver>()) { .observersOf<BoostContainerObserver>()) {
observer(ContainerOperation.Onstage, _onstage.settings); observer(ContainerOperation.Onstage, _onstage.settings);
...@@ -265,7 +269,7 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -265,7 +269,7 @@ class ContainerManagerState extends State<BoostContainerManager> {
setState(() {}); setState(() {});
for (BoostContainerObserver observer in FlutterBoost for (final BoostContainerObserver observer in FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerObserver>()) { .observersOf<BoostContainerObserver>()) {
observer(ContainerOperation.Push, _onstage.settings); observer(ContainerOperation.Push, _onstage.settings);
...@@ -280,9 +284,11 @@ class ContainerManagerState extends State<BoostContainerManager> { ...@@ -280,9 +284,11 @@ class ContainerManagerState extends State<BoostContainerManager> {
_onstage = _offstage.removeLast(); _onstage = _offstage.removeLast();
setState(() {}); setState(() {});
for (BoostContainerObserver observer in FlutterBoost final Set<BoostContainerObserver> observers = FlutterBoost
.singleton.observersHolder .singleton.observersHolder
.observersOf<BoostContainerObserver>()) { .observersOf<BoostContainerObserver>();
for (final BoostContainerObserver observer in observers) {
observer(ContainerOperation.Pop, old.settings); observer(ContainerOperation.Pop, old.settings);
} }
...@@ -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,78 @@ import 'dart:async'; ...@@ -25,58 +25,78 @@ 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<String, dynamic>>('pageOnStart')
.then((Map<String, dynamic> pageInfo) {
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 +109,11 @@ class FlutterBoost { ...@@ -89,10 +109,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 +127,95 @@ class FlutterBoost { ...@@ -106,94 +127,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<String, 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>{};
return channel.invokeMethod<Map<dynamic, dynamic>>('openPage', properties); properties['url'] = url;
properties['urlParams'] = urlParams;
properties['exts'] = exts;
return channel.invokeMethod<Map<String, 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);
} }
}); });
} }
...@@ -12,19 +12,21 @@ class FirstRouteWidget extends StatelessWidget { ...@@ -12,19 +12,21 @@ class FirstRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('First Route'), title: const Text('First Route'),
), ),
body: Center( body: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
RaisedButton( RaisedButton(
child: Text('First'), child: const Text('First'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<String, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -40,19 +42,21 @@ class SecondRouteWidget extends StatelessWidget { ...@@ -40,19 +42,21 @@ class SecondRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Second Route'), title: const Text('Second Route'),
), ),
body: Center( body: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
RaisedButton( RaisedButton(
child: Text('Second'), child: const Text('Second'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<String, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -73,9 +77,11 @@ class _MyAppState extends State<MyApp> { ...@@ -73,9 +77,11 @@ class _MyAppState extends State<MyApp> {
void initState() { void initState() {
super.initState(); super.initState();
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(<String, PageBuilder>{
'first': (pageName, params, _) => FirstRouteWidget(), 'first': (String pageName, Map<String, dynamic> params, String _) =>
'second': (pageName, params, _) => SecondRouteWidget(), FirstRouteWidget(),
'second': (String pageName, Map<String, dynamic> params, String _) =>
SecondRouteWidget(),
}); });
} }
...@@ -88,7 +94,7 @@ class _MyAppState extends State<MyApp> { ...@@ -88,7 +94,7 @@ class _MyAppState extends State<MyApp> {
assert(child is Navigator, 'child must be Navigator, what is wrong?'); assert(child is Navigator, 'child must be Navigator, what is wrong?');
final BoostContainerManager manager = BoostContainerManager( final BoostContainerManager manager = BoostContainerManager(
initNavigator: child, initNavigator: child as Navigator,
); );
return manager; return manager;
...@@ -113,19 +119,23 @@ void main() { ...@@ -113,19 +119,23 @@ void main() {
testWidgets( testWidgets(
'through the `BoostContainerManager.of(context)` method', 'through the `BoostContainerManager.of(context)` method',
(WidgetTester tester) async { (WidgetTester tester) async {
var builderContext; BuildContext builderContext;
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(
'context': (pageName, params, _) => Builder( <String, PageBuilder>{
builder: (context) { 'context':
return FloatingActionButton( (String pageName, Map<String, dynamic> params, String _) =>
onPressed: () { Builder(
builderContext = context; builder: (BuildContext context) {
}, return FloatingActionButton(
); onPressed: () {
}, builderContext = context;
), },
}); );
},
),
},
);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -135,28 +145,34 @@ void main() { ...@@ -135,28 +145,34 @@ void main() {
); );
//open context page //open context page
ContainerCoordinator.singleton ContainerCoordinator.singleton.nativeContainerDidShow(
.nativeContainerDidShow("context", {}, "1000000"); 'context',
<String, dynamic>{},
'1000000',
);
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(find.byType(FloatingActionButton), findsOneWidget); expect(find.byType(FloatingActionButton), findsOneWidget);
//get the context of the Builder //get the context of the Builder
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
final isFind = BoostContainerManager.of(builderContext) != null; final bool isFind = BoostContainerManager.of(builderContext) != null;
expect(isFind, true, expect(
reason: '`BoostContainerManager.of` should be able to ' isFind,
'find `ContainerManagerState` in `FlutterBoost.init()` based on the context of the `Builder`'); true,
reason: '`BoostContainerManager.of` should be able to '
'find `ContainerManagerState` in `FlutterBoost.init()` based on the context of the `Builder`',
);
}, },
); );
// testWidgets( // testWidgets(
// 'through the `BoostContainerManager.of(context)` method', // 'through the `BoostContainerManager.of(context)` method',
// (WidgetTester tester) async { // (WidgetTester tester) async {
// var builderContext; // BuildContext builderContext;
// //
// await tester.pumpWidget( // await tester.pumpWidget(
// MaterialApp( // MaterialApp(
...@@ -184,19 +200,22 @@ void main() { ...@@ -184,19 +200,22 @@ void main() {
testWidgets( testWidgets(
'through the `BoostContainerManager.tryOf(context)` method', 'through the `BoostContainerManager.tryOf(context)` method',
(WidgetTester tester) async { (WidgetTester tester) async {
var builderContext; BuildContext builderContext;
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(
'context': (pageName, params, _) => Builder( <String, PageBuilder>{
builder: (context) { 'context': (String pageName, Map<String, dynamic> params, _) =>
return FloatingActionButton( Builder(
onPressed: () { builder: (BuildContext context) {
builderContext = context; return FloatingActionButton(
}, onPressed: () {
); builderContext = context;
}, },
), );
}); },
),
},
);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -206,21 +225,25 @@ void main() { ...@@ -206,21 +225,25 @@ void main() {
); );
//open context page //open context page
ContainerCoordinator.singleton ContainerCoordinator.singleton.nativeContainerDidShow(
.nativeContainerDidShow("context", {}, "1000000"); 'context', <String, dynamic>{}, '1000000');
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(find.byType(FloatingActionButton), findsOneWidget); expect(find.byType(FloatingActionButton), findsOneWidget);
//get the context of the Builder //get the context of the Builder
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
final isFind = BoostContainerManager.tryOf(builderContext) != null; final bool isFind =
BoostContainerManager.tryOf(builderContext) != null;
expect(isFind, true, expect(
reason: '`BoostContainerManager.tryOf` should be able to ' isFind,
'find `ContainerManagerState` in `FlutterBoost.init()` based on the context of the `Builder`'); true,
reason: '`BoostContainerManager.tryOf` should be able to '
'find `ContainerManagerState` in `FlutterBoost.init()` based on the context of the `Builder`',
);
}, },
); );
}, },
...@@ -230,19 +253,22 @@ void main() { ...@@ -230,19 +253,22 @@ void main() {
testWidgets( testWidgets(
'containerCounts should change based on the number of pages', 'containerCounts should change based on the number of pages',
(WidgetTester tester) async { (WidgetTester tester) async {
var builderContext; BuildContext builderContext;
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(
'context': (pageName, params, _) => Builder( <String, PageBuilder>{
builder: (context) { 'context': (String pageName, Map<String, dynamic> params, _) =>
return FloatingActionButton( Builder(
onPressed: () { builder: (BuildContext context) {
builderContext = context; return FloatingActionButton(
}, onPressed: () {
); builderContext = context;
}, },
), );
}); },
),
},
);
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -253,23 +279,24 @@ void main() { ...@@ -253,23 +279,24 @@ void main() {
//open first context page //open first context page
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("context", {}, "1000000"); .nativeContainerDidShow('context', <String, dynamic>{}, '1000000');
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
//get the context of the Builder //get the context of the Builder
await tester.tap(find.byType(FloatingActionButton)); await tester.tap(find.byType(FloatingActionButton));
final containerManagerState = BoostContainerManager.of(builderContext); final ContainerManagerState containerManagerState =
BoostContainerManager.of(builderContext);
expect(containerManagerState.containerCounts, 1, expect(containerManagerState.containerCounts, 1,
reason: '1 page shown'); reason: '1 page shown');
//open second context page //open second context page
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("context", {}, "2000000"); .nativeContainerDidShow('context', <String, dynamic>{}, '2000000');
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(containerManagerState.containerCounts, 2, expect(containerManagerState.containerCounts, 2,
reason: '2 page shown'); reason: '2 page shown');
...@@ -277,7 +304,7 @@ void main() { ...@@ -277,7 +304,7 @@ void main() {
//pop second context page //pop second context page
containerManagerState.pop(); containerManagerState.pop();
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(containerManagerState.containerCounts, 1, expect(containerManagerState.containerCounts, 1,
reason: 'second context page closed, Only one page left'); reason: 'second context page closed, Only one page left');
...@@ -285,7 +312,7 @@ void main() { ...@@ -285,7 +312,7 @@ void main() {
//pop last context page //pop last context page
containerManagerState.pop(); containerManagerState.pop();
await tester.pump(Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(containerManagerState.containerCounts, 0, expect(containerManagerState.containerCounts, 0,
reason: 'last context page closed, no page left'); reason: 'last context page closed, no page left');
......
import 'package:flutter_boost/container/container_manager.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_boost/flutter_boost.dart'; import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_boost/container/container_manager.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
test('test onMethodCall', () async {
FlutterBoost.singleton.registerDefaultPageBuilder(
(String pageName, Map<String, dynamic> params, String _) =>
Container());
FlutterBoost.singleton.addContainerObserver(
(ContainerOperation operation, BoostContainerSettings settings) {},
);
FlutterBoost.singleton.addBoostContainerLifeCycleObserver(
(ContainerLifeCycle state, BoostContainerSettings settings) {},
);
FlutterBoost.singleton.addBoostNavigatorObserver(NavigatorObserver());
try {
FlutterBoost.singleton.open('url');
} catch (e) {
expect(e, isException);
}
try {
FlutterBoost.singleton.close('url');
} catch (e) {
expect(e, isNoSuchMethodError);
}
try {
FlutterBoost.singleton.closeCurrent(
result: <String, dynamic>{},
exts: <String, dynamic>{},
);
} catch (e) {
expect(e, isNoSuchMethodError);
}
// test('test onMethodCall', () async { try {
// FlutterBoost.singleton FlutterBoost.singleton.closeByContext(
// .registerDefaultPageBuilder((pageName, params, _) => Container()); null,
// FlutterBoost.singleton.addContainerObserver( result: <String, dynamic>{},
// (ContainerOperation operation, BoostContainerSettings settings) {}); exts: <String, dynamic>{},
// );
// FlutterBoost.singleton.addBoostContainerLifeCycleObserver( } catch (e) {
// (ContainerLifeCycle state, BoostContainerSettings settings) {}); expect(e, isNoSuchMethodError);
// }
// FlutterBoost.singleton.addBoostNavigatorObserver(NavigatorObserver()); });
//
// try {
// FlutterBoost.singleton.open("url");
// } catch (e) {
// expect(e, isException);
// }
// try {
// FlutterBoost.singleton.close("url");
// } catch (e) {
// expect(e, isNoSuchMethodError);
// }
// try {
// FlutterBoost.singleton.closeCurrent(result: <String,dynamic>{}, exts: <String,dynamic>{});
// } catch (e) {
// expect(e, isNoSuchMethodError);
// }
//
// try {
// FlutterBoost.singleton.closeByContext(null, result: <String,dynamic>{}, exts: <String,dynamic>{});
// } catch (e) {
// expect(e, isNoSuchMethodError);
// }
// });
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_boost/flutter_boost.dart'; import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_boost/container/container_coordinator.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'page_widgets.dart'; import 'page_widgets.dart';
import 'package:flutter_boost/container/container_coordinator.dart';
class MyApp extends StatefulWidget { class MyApp extends StatefulWidget {
@override @override
...@@ -15,14 +16,19 @@ class _MyAppState extends State<MyApp> { ...@@ -15,14 +16,19 @@ class _MyAppState extends State<MyApp> {
void initState() { void initState() {
super.initState(); super.initState();
FlutterBoost.singleton.registerPageBuilders({ FlutterBoost.singleton.registerPageBuilders(<String, PageBuilder>{
'embeded': (pageName, params, _) => EmbededFirstRouteWidget(), 'embeded': (String pageName, Map<String, dynamic> params, _) =>
'first': (pageName, params, _) => FirstRouteWidget(), EmbededFirstRouteWidget(),
'second': (pageName, params, _) => SecondRouteWidget(), 'first': (String pageName, Map<String, dynamic> params, _) =>
'tab': (pageName, params, _) => TabRouteWidget(), FirstRouteWidget(),
'flutterFragment': (pageName, params, _) => FragmentRouteWidget(params), 'second': (String pageName, Map<String, dynamic> params, _) =>
'flutterPage': (pageName, params, _) { SecondRouteWidget(),
print("flutterPage params:$params"); 'tab': (String pageName, Map<String, dynamic> params, _) =>
TabRouteWidget(),
'flutterFragment': (String pageName, Map<String, dynamic> params, _) =>
FragmentRouteWidget(params),
'flutterPage': (String pageName, Map<String, dynamic> params, _) {
print('flutterPage params:$params');
return FlutterRouteWidget(params: params); return FlutterRouteWidget(params: params);
}, },
...@@ -40,24 +46,33 @@ class _MyAppState extends State<MyApp> { ...@@ -40,24 +46,33 @@ class _MyAppState extends State<MyApp> {
} }
void _onRoutePushed( void _onRoutePushed(
String pageName, String uniqueId, Map params, Route route, Future _) {} String pageName,
String uniqueId,
Map<String, dynamic> params,
Route<dynamic> route,
Future<dynamic> _,
) {}
} }
class TestBoostNavigatorObserver extends NavigatorObserver { class TestBoostNavigatorObserver extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { void didPush(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didPush"); print('flutterboost#didPush');
} }
@override
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) { void didPop(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didPop"); print('flutterboost#didPop');
} }
@override
void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) { void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) {
print("flutterboost#didRemove"); print('flutterboost#didRemove');
} }
@override
void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) { void didReplace({Route<dynamic> newRoute, Route<dynamic> oldRoute}) {
print("flutterboost#didReplace"); print('flutterboost#didReplace');
} }
} }
...@@ -72,7 +87,7 @@ void main() { ...@@ -72,7 +87,7 @@ void main() {
); );
//open firt page //open firt page
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("first", <dynamic,dynamic>{}, "1000000"); .nativeContainerDidShow('first', <String, dynamic>{}, '1000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -80,7 +95,7 @@ void main() { ...@@ -80,7 +95,7 @@ void main() {
//open second page firt(1000000)->second(2000000) //open second page firt(1000000)->second(2000000)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("second", <dynamic,dynamic>{}, "2000000"); .nativeContainerDidShow('second', <String, dynamic>{}, '2000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -89,7 +104,7 @@ void main() { ...@@ -89,7 +104,7 @@ void main() {
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
//close sencod page firt(1000000) //close sencod page firt(1000000)
FlutterBoost.containerManager?.remove("2000000"); FlutterBoost.containerManager?.remove('2000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -97,7 +112,7 @@ void main() { ...@@ -97,7 +112,7 @@ void main() {
// second page ,but pageId is 2000001 firt(1000000)->second(2000001) // second page ,but pageId is 2000001 firt(1000000)->second(2000001)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("second", <dynamic,dynamic>{}, "2000001"); .nativeContainerDidShow('second', <String, dynamic>{}, '2000001');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -107,7 +122,7 @@ void main() { ...@@ -107,7 +122,7 @@ void main() {
//reopen firt page second(2000001)->firt(1000000) //reopen firt page second(2000001)->firt(1000000)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("first",<dynamic,dynamic> {}, "1000000"); .nativeContainerDidShow('first', <String, dynamic>{}, '1000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -117,7 +132,7 @@ void main() { ...@@ -117,7 +132,7 @@ void main() {
// reopen second page and pageId is 2000001 firt(1000000)->second(2000001) // reopen second page and pageId is 2000001 firt(1000000)->second(2000001)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("second", <dynamic,dynamic>{}, "2000001"); .nativeContainerDidShow('second', <String, dynamic>{}, '2000001');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
...@@ -126,24 +141,18 @@ void main() { ...@@ -126,24 +141,18 @@ void main() {
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
//close firt(1000000) page second(2000001) //close firt(1000000) page second(2000001)
FlutterBoost.containerManager?.remove("1000000"); FlutterBoost.containerManager?.remove('1000000');
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(find.text('Second'), findsOneWidget); expect(find.text('Second'), findsOneWidget);
// open second(2000003) // open second(2000003)
ContainerCoordinator.singleton ContainerCoordinator.singleton
.nativeContainerDidShow("second", <dynamic,dynamic>{}, "2000003"); .nativeContainerDidShow('second', <String, dynamic>{}, '2000003');
await tester.idle(); await tester.idle();
expect(find.text('Second'), findsOneWidget); expect(find.text('Second'), findsOneWidget);
}); });
} }
...@@ -7,36 +7,38 @@ class FirstRouteWidget extends StatelessWidget { ...@@ -7,36 +7,38 @@ class FirstRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('First Route'), title: const Text('First Route'),
), ),
body: Center( body: Center(
child: child: Column(
Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: children: <Widget>[
<Widget>[
RaisedButton( RaisedButton(
child: Text('First'), child: const Text('First'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
print( .open('second')
"call me when page is finished. did recieve second route result $value"); .then((Map<String, dynamic> value) {
}); print(
}, 'call me when page is finished. did recieve second route result $value');
), });
},
RaisedButton( ),
child: Text('Present second route'), RaisedButton(
onPressed: () { child: const Text('Present second route'),
print("Present second page!"); onPressed: () {
FlutterBoost.singleton.open("second",urlParams:<dynamic,dynamic>{"present":true}).then((Map value) { print('Present second page!');
print( FlutterBoost.singleton.open('second',
"call me when page is finished. did recieve second route result $value"); urlParams: <String, dynamic>{
}); 'present': true
}, }).then((Map<String, dynamic> value) {
), print(
], 'call me when page is finished. did recieve second route result $value');
});
},
),
],
), ),
), ),
); );
...@@ -49,12 +51,14 @@ class EmbededFirstRouteWidget extends StatelessWidget { ...@@ -49,12 +51,14 @@ class EmbededFirstRouteWidget extends StatelessWidget {
return Scaffold( return Scaffold(
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
child: Text('Open second route'), child: const Text('Open second route'),
onPressed: () { onPressed: () {
print("open second page!"); print('open second page!');
FlutterBoost.singleton.open("second").then((Map value) { FlutterBoost.singleton
.open('second')
.then((Map<String, dynamic> value) {
print( print(
"call me when page is finished. did recieve second route result $value"); 'call me when page is finished. did recieve second route result $value');
}); });
}, },
), ),
...@@ -68,19 +72,19 @@ class SecondRouteWidget extends StatelessWidget { ...@@ -68,19 +72,19 @@ class SecondRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text("Second"), title: const Text('Second'),
), ),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
// Navigate back to first route when tapped. // Navigate back to first route when tapped.
BoostContainerSettings settings = final BoostContainerSettings settings =
BoostContainer.of(context).settings; BoostContainer.of(context).settings;
FlutterBoost.singleton.close(settings.uniqueId, FlutterBoost.singleton.close(settings.uniqueId,
result:<dynamic,dynamic>{"result": "data from second"}); result: <String, dynamic>{'result': 'data from second'});
}, },
child: Text('Go back with result!'), child: const Text('Go back with result!'),
), ),
), ),
); );
...@@ -92,14 +96,14 @@ class TabRouteWidget extends StatelessWidget { ...@@ -92,14 +96,14 @@ class TabRouteWidget extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text("Tab Route"), title: const Text('Tab Route'),
), ),
body: Center( body: Center(
child: RaisedButton( child: RaisedButton(
onPressed: () { onPressed: () {
FlutterBoost.singleton.open("second"); FlutterBoost.singleton.open('second');
}, },
child: Text('Open second route'), child: const Text('Open second route'),
), ),
), ),
); );
...@@ -107,8 +111,9 @@ class TabRouteWidget extends StatelessWidget { ...@@ -107,8 +111,9 @@ class TabRouteWidget extends StatelessWidget {
} }
class FlutterRouteWidget extends StatefulWidget { class FlutterRouteWidget extends StatefulWidget {
FlutterRouteWidget({this.params,this.message}); const FlutterRouteWidget({this.params, this.message});
final Map params;
final Map<String, dynamic> params;
final String message; final String message;
@override @override
...@@ -116,176 +121,190 @@ class FlutterRouteWidget extends StatefulWidget { ...@@ -116,176 +121,190 @@ class FlutterRouteWidget extends StatefulWidget {
} }
class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
final TextEditingController _usernameController = TextEditingController();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final String message=widget.message; final String message = widget.message;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
brightness:Brightness.light, brightness: Brightness.light,
backgroundColor: Colors.white, backgroundColor: Colors.white,
textTheme:new TextTheme(title: TextStyle(color: Colors.black)) , textTheme: TextTheme(title: TextStyle(color: Colors.black)),
title: const Text('flutter_boost_example'),
title: Text('flutter_boost_example'),
), ),
body: SingleChildScrollView( body: SingleChildScrollView(
child:Container( child: Container(
margin: const EdgeInsets.all(24.0), margin: const EdgeInsets.all(24.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Container( Container(
margin: const EdgeInsets.only(top: 10.0,bottom: 20.0), margin: const EdgeInsets.only(top: 10.0, bottom: 20.0),
child: Text( child: Text(
message ?? "This is a flutter activity \n params:${widget.params}", message ??
style: TextStyle(fontSize: 28.0, color: Colors.blue), 'This is a flutter activity \n params:${widget.params}',
), style: TextStyle(fontSize: 28.0, color: Colors.blue),
alignment: AlignmentDirectional.center,
), ),
// Expanded(child: Container()), alignment: AlignmentDirectional.center,
const CupertinoTextField( ),
prefix: Icon( const CupertinoTextField(
CupertinoIcons.person_solid, prefix: Icon(
color: CupertinoColors.lightBackgroundGray, CupertinoIcons.person_solid,
size: 28.0, color: CupertinoColors.lightBackgroundGray,
size: 28.0,
),
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 12.0),
clearButtonMode: OverlayVisibilityMode.editing,
textCapitalization: TextCapitalization.words,
autocorrect: false,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 0.0, color: CupertinoColors.inactiveGray),
), ),
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 12.0), ),
clearButtonMode: OverlayVisibilityMode.editing, placeholder: 'Name',
textCapitalization: TextCapitalization.words, ),
autocorrect: false, InkWell(
decoration: BoxDecoration( child: Container(
border: Border(bottom: BorderSide(width: 0.0, color: CupertinoColors.inactiveGray)), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black),
), ),
placeholder: 'Name',
), ),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("sample://nativePage", urlParams: <dynamic,dynamic>{ 'sample://nativePage',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'},
},
), ),
InkWell( ),
child: Container( InkWell(
padding: const EdgeInsets.all(8.0), child: Container(
margin: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
color: Colors.yellow, margin: const EdgeInsets.all(8.0),
child: Text( color: Colors.yellow,
'open first', child: Text(
style: TextStyle(fontSize: 22.0, color: Colors.black), 'open first',
)), style: TextStyle(fontSize: 22.0, color: Colors.black),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton
.open("first", urlParams: <dynamic,dynamic>{
"query": {"aaa": "bbb"}
}),
), ),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'open second',
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("second", urlParams: <dynamic,dynamic>{ 'first',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'},
},
), ),
InkWell( ),
child: Container( InkWell(
padding: const EdgeInsets.all(8.0), child: Container(
margin: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
color: Colors.yellow, margin: const EdgeInsets.all(8.0),
child: Text( color: Colors.yellow,
'open tab', child: Text(
style: TextStyle(fontSize: 22.0, color: Colors.black), 'open second',
)), style: TextStyle(fontSize: 22.0, color: Colors.black),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton
.open("tab", urlParams: <dynamic,dynamic>{
"query": {"aaa": "bbb"}
}),
), ),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。 ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb ///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton onTap: () => FlutterBoost.singleton.open(
.open("sample://flutterPage", urlParams:<dynamic,dynamic> { 'second',
"query": {"aaa": "bbb"} urlParams: <String, dynamic>{
}), 'query': <String, dynamic>{'aaa': 'bbb'},
},
),
),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'open tab',
style: TextStyle(fontSize: 22.0, color: Colors.black),
),
), ),
InkWell(
child: Container( ///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
padding: const EdgeInsets.all(8.0), ///例如:sample://nativePage?aaa=bbb
margin: const EdgeInsets.all(8.0), onTap: () => FlutterBoost.singleton.open(
color: Colors.yellow, 'tab',
child: Text( urlParams: <String, dynamic>{
'push flutter widget', 'query': <String, dynamic>{'aaa': 'bbb'}
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
onTap: () {
Navigator.push<dynamic>(context,
MaterialPageRoute<dynamic>(builder: (_) => PushWidget()));
}, },
), ),
),
InkWell(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black),
),
),
///后面的参数会在native的IPlatform.startActivity方法回调中拼接到url的query部分。
///例如:sample://nativePage?aaa=bbb
onTap: () => FlutterBoost.singleton.open(
'sample://flutterPage',
urlParams: <String, dynamic>{
'query': <String, dynamic>{'aaa': 'bbb'}
},
),
),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: Text(
'push Platform demo', 'push flutter widget',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () { onTap: () {
Navigator.push<dynamic>(
context,
MaterialPageRoute<dynamic>(builder: (_) => PushWidget()),
);
}, },
), ),
InkWell( InkWell(
child: Container( child: Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(8.0),
color: Colors.yellow, color: Colors.yellow,
child: Text( child: Text(
'open flutter fragment page', 'push Platform demo',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => FlutterBoost.singleton onTap: () {},
.open("sample://flutterFragmentPage"), ),
), InkWell(
], child: Container(
), padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
color: Colors.yellow,
child: Text(
'open flutter fragment page',
style: TextStyle(fontSize: 22.0, color: Colors.black),
)),
onTap: () =>
FlutterBoost.singleton.open('sample://flutterFragmentPage'),
),
],
),
), ),
), ),
); );
...@@ -293,15 +312,15 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> { ...@@ -293,15 +312,15 @@ class _FlutterRouteWidgetState extends State<FlutterRouteWidget> {
} }
class FragmentRouteWidget extends StatelessWidget { class FragmentRouteWidget extends StatelessWidget {
final Map params; const FragmentRouteWidget(this.params);
FragmentRouteWidget(this.params); final Map<String, dynamic> params;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('flutter_boost_example'), title: const Text('flutter_boost_example'),
), ),
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
...@@ -309,7 +328,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -309,7 +328,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 80.0), margin: const EdgeInsets.only(top: 80.0),
child: Text( child: Text(
"This is a flutter fragment", 'This is a flutter fragment',
style: TextStyle(fontSize: 28.0, color: Colors.blue), style: TextStyle(fontSize: 28.0, color: Colors.blue),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -317,7 +336,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -317,7 +336,7 @@ class FragmentRouteWidget extends StatelessWidget {
Container( Container(
margin: const EdgeInsets.only(top: 32.0), margin: const EdgeInsets.only(top: 32.0),
child: Text( child: Text(
params['tag'] ?? '', '${params['tag']}' ?? '',
style: TextStyle(fontSize: 28.0, color: Colors.red), style: TextStyle(fontSize: 28.0, color: Colors.red),
), ),
alignment: AlignmentDirectional.center, alignment: AlignmentDirectional.center,
...@@ -332,7 +351,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -332,7 +351,7 @@ class FragmentRouteWidget extends StatelessWidget {
'open native page', 'open native page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => FlutterBoost.singleton.open("sample://nativePage"), onTap: () => FlutterBoost.singleton.open('sample://nativePage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -343,7 +362,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -343,7 +362,7 @@ class FragmentRouteWidget extends StatelessWidget {
'open flutter page', 'open flutter page',
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => FlutterBoost.singleton.open("sample://flutterPage"), onTap: () => FlutterBoost.singleton.open('sample://flutterPage'),
), ),
InkWell( InkWell(
child: Container( child: Container(
...@@ -355,7 +374,7 @@ class FragmentRouteWidget extends StatelessWidget { ...@@ -355,7 +374,7 @@ class FragmentRouteWidget extends StatelessWidget {
style: TextStyle(fontSize: 22.0, color: Colors.black), style: TextStyle(fontSize: 22.0, color: Colors.black),
)), )),
onTap: () => onTap: () =>
FlutterBoost.singleton.open("sample://flutterFragmentPage"), FlutterBoost.singleton.open('sample://flutterFragmentPage'),
) )
], ],
), ),
...@@ -373,13 +392,13 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -373,13 +392,13 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
void initState() { void initState() {
// TODO: implement initState // TODO(unknown): implement initState
super.initState(); super.initState();
} }
@override @override
void didChangeDependencies() { void didChangeDependencies() {
// TODO: implement didChangeDependencies // TODO(unknown): implement didChangeDependencies
super.didChangeDependencies(); super.didChangeDependencies();
// if (_backPressedListenerUnsub == null) { // if (_backPressedListenerUnsub == null) {
...@@ -395,13 +414,13 @@ class _PushWidgetState extends State<PushWidget> { ...@@ -395,13 +414,13 @@ class _PushWidgetState extends State<PushWidget> {
@override @override
void dispose() { void dispose() {
// TODO: implement dispose // TODO(unknown): implement dispose
super.dispose(); super.dispose();
_backPressedListenerUnsub?.call(); _backPressedListenerUnsub?.call();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FlutterRouteWidget(message: "Pushed Widget"); return const FlutterRouteWidget(message: 'Pushed Widget');
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment