25 |
26 | + (instancetype)sharedInstance;
27 |
28 | + (instancetype)new NS_UNAVAILABLE;
29 | - (instancetype)init NS_UNAVAILABLE;
30 |
31 | - (void)invokeMethod:(NSString *_Nullable)method
32 | arguments:(id _Nullable)arguments
33 | result:(FlutterResult _Nullable)callback;
34 | @end
35 |
36 | NS_ASSUME_NONNULL_END
37 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/io/flutter/embedding/android/DViewUtils.java:
--------------------------------------------------------------------------------
1 | // Copyright 2013 The Flutter Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style license that can be
3 | // found in the LICENSE file.
4 |
5 | package io.flutter.embedding.android;
6 |
7 | import android.app.Activity;
8 | import android.content.Context;
9 | import android.content.ContextWrapper;
10 | import android.os.Build;
11 | import android.view.View;
12 |
13 | public final class DViewUtils {
14 | /**
15 | * Retrieves the {@link Activity} from a given {@link Context}.
16 | *
17 | * This method will recursively traverse up the context chain if it is a {@link ContextWrapper}
18 | * until it finds the first instance of the base context that is an {@link Activity}.
19 | */
20 | public static Activity getActivity(Context context) {
21 | if (context == null) {
22 | return null;
23 | }
24 | if (context instanceof Activity) {
25 | return (Activity) context;
26 | }
27 | if (context instanceof ContextWrapper) {
28 | // Recurse up chain of base contexts until we find an Activity.
29 | return getActivity(((ContextWrapper) context).getBaseContext());
30 | }
31 | return null;
32 | }
33 |
34 | /**
35 | * Generates a view id.
36 | *
37 | *
In API level 17 and above, this ID is unique. Below 17, the fallback id is used instead.
38 | *
39 | * @param fallbackId the fallback id.
40 | * @return the view id.
41 | */
42 | public static int generateViewId(int fallbackId) {
43 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
44 | return View.generateViewId();
45 | }
46 | return fallbackId;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/tal/com/d_stack/lifecycle/PageModel.java:
--------------------------------------------------------------------------------
1 | package tal.com.d_stack.lifecycle;
2 |
3 |
4 | /**
5 | * 页面状态信息
6 | */
7 | public class PageModel {
8 |
9 | // 当前展示的页面路由
10 | private String currentPageRoute;
11 | // 前一个展示的页面路由,可能为null
12 | private String prePageRoute;
13 | // 页面类型:Flutter/Native
14 | private String currentPageType;
15 | // 页面类型:Flutter/Native
16 | private String prePageType;
17 | // 操作类型:push/pop
18 | private String actionType;
19 | // 应用状态 0:应用启动 1:前台 2:后台 3:应用杀死
20 | private int state = 0;
21 |
22 | public String getCurrentPageRoute() {
23 | return currentPageRoute;
24 | }
25 |
26 | public void setCurrentPageRoute(String currentPageRoute) {
27 | this.currentPageRoute = currentPageRoute;
28 | }
29 |
30 | public String getPrePageRoute() {
31 | return prePageRoute;
32 | }
33 |
34 | public void setPrePageRoute(String prePageRoute) {
35 | this.prePageRoute = prePageRoute;
36 | }
37 |
38 | public String getCurrentPageType() {
39 | return currentPageType;
40 | }
41 |
42 | public void setCurrentPageType(String currentPageType) {
43 | this.currentPageType = currentPageType;
44 | }
45 |
46 | public String getPrePageType() {
47 | return prePageType;
48 | }
49 |
50 | public void setPrePageType(String prePageType) {
51 | this.prePageType = prePageType;
52 | }
53 |
54 | public String getActionType() {
55 | return actionType;
56 | }
57 |
58 | public void setActionType(String actionType) {
59 | this.actionType = actionType;
60 | }
61 |
62 | public int getState() {
63 | return state;
64 | }
65 |
66 | public void setState(int state) {
67 | this.state = state;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: d_stack_example
2 | description: Demonstrates how to use the d_stack plugin.
3 | publish_to: 'none'
4 |
5 | environment:
6 | sdk: '>=2.12.0 <3.0.0'
7 |
8 | dependencies:
9 | flutter:
10 | sdk: flutter
11 | d_stack:
12 | path: ../
13 |
14 | # The following adds the Cupertino Icons font to your application.
15 | # Use with the CupertinoIcons class for iOS style icons.
16 | cupertino_icons: 0.1.3
17 |
18 | dev_dependencies:
19 | flutter_test:
20 | sdk: flutter
21 |
22 |
23 | # For information on the generic Dart part of this file, see the
24 | # following page: https://dart.dev/tools/pub/pubspec
25 |
26 | # The following section is specific to Flutter.
27 | flutter:
28 |
29 | # The following line ensures that the Material Icons font is
30 | # included with your application, so that you can use the icons in
31 | # the material Icons class.
32 | uses-material-design: true
33 |
34 | # To add assets to your application, add an assets section, like this:
35 | # assets:
36 | # - images/a_dot_burr.jpeg
37 | # - images/a_dot_ham.jpeg
38 |
39 | # An image asset can refer to one or more resolution-specific "variants", see
40 | # https://flutter.dev/assets-and-images/#resolution-aware.
41 |
42 | # For details regarding adding assets from package dependencies, see
43 | # https://flutter.dev/assets-and-images/#from-packages
44 |
45 | # To add custom fonts to your application, add a fonts section here,
46 | # in this "flutter" section. Each entry in this list should have a
47 | # "family" key with the font family name, and a "fonts" key with a
48 | # list giving the asset and other descriptors for the font. For
49 | # example:
50 | # fonts:
51 | # - family: Schyler
52 | # fonts:
53 | # - asset: fonts/Schyler-Regular.ttf
54 | # - asset: fonts/Schyler-Italic.ttf
55 | # style: italic
56 | # - family: Trajan Pro
57 | # fonts:
58 | # - asset: fonts/TrajanPro.ttf
59 | # - asset: fonts/TrajanPro_Bold.ttf
60 | # weight: 700
61 | #
62 | # For details regarding fonts from package dependencies,
63 | # see https://flutter.dev/custom-fonts/#from-packages
64 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 29
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "tal.com.d_stack_example"
42 | minSdkVersion 21
43 | targetSdkVersion 29
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
47 | }
48 |
49 | buildTypes {
50 | release {
51 | // TODO: Add your own signing config for the release build.
52 | // Signing with the debug keys for now, so `flutter run --release` works.
53 | signingConfig signingConfigs.debug
54 | }
55 | }
56 | }
57 |
58 | flutter {
59 | source '../..'
60 | }
61 |
62 | dependencies {
63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
64 | implementation 'androidx.appcompat:appcompat:1.2.0-alpha03'
65 | }
66 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
14 |
15 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
46 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/tal/com/d_stack/DStackPlugin.kt:
--------------------------------------------------------------------------------
1 | package tal.com.d_stack
2 |
3 | import androidx.annotation.NonNull;
4 | import io.flutter.embedding.engine.plugins.FlutterPlugin
5 | import io.flutter.plugin.common.MethodCall
6 | import io.flutter.plugin.common.MethodChannel
7 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler
8 | import io.flutter.plugin.common.MethodChannel.Result
9 | import io.flutter.plugin.common.PluginRegistry.Registrar
10 | import tal.com.d_stack.channel.DStackMethodHandler
11 |
12 | /**
13 | * DStackPlugin
14 | */
15 | public class DStackPlugin : FlutterPlugin, MethodCallHandler {
16 | override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
17 | val channel = MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "d_stack")
18 | channel.setMethodCallHandler(DStackMethodHandler())
19 | }
20 |
21 | // This static function is optional and equivalent to onAttachedToEngine. It supports the old
22 | // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
23 | // plugin registration via this function while apps migrate to use the new Android APIs
24 | // post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
25 | //
26 | // It is encouraged to share logic between onAttachedToEngine and registerWith to keep
27 | // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
28 | // depending on the user's project. onAttachedToEngine or registerWith must both be defined
29 | // in the same class.
30 | companion object {
31 | @JvmStatic
32 | fun registerWith(registrar: Registrar) {
33 | val channel = MethodChannel(registrar.messenger(), "d_stack")
34 | channel.setMethodCallHandler(DStackPlugin())
35 | }
36 | }
37 |
38 | override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
39 | if (call.method == "getPlatformVersion") {
40 | result.success("Android ${android.os.Build.VERSION.RELEASE}")
41 | } else {
42 | result.notImplemented()
43 | }
44 | }
45 |
46 | override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: d_stack
2 | description: 混合栈
3 | version: 1.3.4+3-nullsafety
4 | author: peter
5 | homepage: https://github.com/tal-tech/d_stack
6 |
7 | environment:
8 | sdk: ">=2.12.0 <3.0.0"
9 | flutter: ">=2.0.0"
10 |
11 | dependencies:
12 | flutter:
13 | sdk: flutter
14 |
15 | dev_dependencies:
16 | flutter_test:
17 | sdk: flutter
18 |
19 | # For information on the generic Dart part of this file, see the
20 | # following page: https://dart.dev/tools/pub/pubspec
21 |
22 | # The following section is specific to Flutter.
23 | flutter:
24 | # This section identifies this Flutter project as a plugin project.
25 | # The 'pluginClass' and Android 'package' identifiers should not ordinarily
26 | # be modified. They are used by the tooling to maintain consistency when
27 | # adding or updating assets for this project.
28 | plugin:
29 | platforms:
30 | android:
31 | package: tal.com.d_stack
32 | pluginClass: DStackPlugin
33 | ios:
34 | pluginClass: DStackPlugin
35 |
36 | # To add assets to your plugin package, add an assets section, like this:
37 | # assets:
38 | # - images/a_dot_burr.jpeg
39 | # - images/a_dot_ham.jpeg
40 | #
41 | # For details regarding assets in packages, see
42 | # https://flutter.dev/assets-and-images/#from-packages
43 | #
44 | # An image asset can refer to one or more resolution-specific "variants", see
45 | # https://flutter.dev/assets-and-images/#resolution-aware.
46 |
47 | # To add custom fonts to your plugin package, add a fonts section here,
48 | # in this "flutter" section. Each entry in this list should have a
49 | # "family" key with the font family name, and a "fonts" key with a
50 | # list giving the asset and other descriptors for the font. For
51 | # example:
52 | # fonts:
53 | # - family: Schyler
54 | # fonts:
55 | # - asset: fonts/Schyler-Regular.ttf
56 | # - asset: fonts/Schyler-Italic.ttf
57 | # style: italic
58 | # - family: Trajan Pro
59 | # fonts:
60 | # - asset: fonts/TrajanPro.ttf
61 | # - asset: fonts/TrajanPro_Bold.ttf
62 | # weight: 700
63 | #
64 | # For details regarding fonts in packages, see
65 | # https://flutter.dev/custom-fonts/#from-packages
66 |
67 |
--------------------------------------------------------------------------------
/android/src/main/kotlin/tal/com/d_stack/observer/FilterActivityManager.java:
--------------------------------------------------------------------------------
1 | package tal.com.d_stack.observer;
2 |
3 | import android.app.Activity;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 | import java.util.concurrent.atomic.AtomicReference;
8 |
9 | /**
10 | * 需要过滤的第三方activity管理
11 | */
12 | public class FilterActivityManager {
13 |
14 | private final static AtomicReference INSTANCE = new AtomicReference<>();
15 |
16 | public static FilterActivityManager getInstance() {
17 | for (; ; ) {
18 | FilterActivityManager factory = INSTANCE.get();
19 | if (factory != null) {
20 | return factory;
21 | }
22 | factory = new FilterActivityManager();
23 | if (INSTANCE.compareAndSet(null, factory)) {
24 | return factory;
25 | }
26 | }
27 | }
28 |
29 | private FilterActivityManager() {
30 | filterActivities.add("rom.huawei");
31 | filterActivities.add("rom.oppo");
32 | filterActivities.add("com.tencent");
33 | filterActivities.add("com.sina");
34 | filterActivities.add("com.tal.d_stack_spy");
35 | filterActivities.add("com.yorhp");
36 | }
37 |
38 | private List filterActivities = new ArrayList<>();
39 |
40 | private List androidStack = new ArrayList<>();
41 |
42 | /**
43 | * 判断是否可以添加到混合栈
44 | * @param activity
45 | * @return
46 | */
47 | public boolean canAdd(Activity activity) {
48 | if (activity == null) {
49 | return false;
50 | }
51 | String fullName = activity.getClass().getName();
52 | for (String filterName : filterActivities) {
53 | if (fullName.contains(filterName)) {
54 | return false;
55 | }
56 | }
57 | return true;
58 | }
59 |
60 | /**
61 | * 添加过滤器
62 | * 某些功能性Activity,不需要做节点管理的,添加至过滤
63 | *
64 | * @param filterString 过滤字符串
65 | * @return
66 | */
67 | public boolean addFilter(String filterString) {
68 | return filterActivities.add(filterString);
69 | }
70 |
71 | /**
72 | * 移除已添加的过滤器
73 | *
74 | * @param filterString
75 | * @return
76 | */
77 | public boolean removeFilter(String filterString) {
78 | return filterActivities.remove(filterString);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Classes/Node/DNodeManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // DNodeManager.h
3 | // 管理节点信息
4 | //
5 | // Created by TAL on 2020/1/16.
6 | //
7 |
8 | #import
9 | #import "DNode.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | /// Node节点管理器
14 | /// 全链路全节点记录
15 | /// Flutter页面打开、关闭都会发消息至Native侧进行节点管理
16 | /// Native页面打开、关闭都会发消息至Native侧进行节点管理
17 | @interface DNodeManager : NSObject
18 |
19 | /// 当前的节点列表
20 | @property (nonatomic, strong, readonly) NSArray *currentNodeList;
21 |
22 | /// 当前显示的节点
23 | @property (nonatomic, strong, readonly, nullable) DNode *currentNode;
24 |
25 | /// 当前显示的节点的前一个节点
26 | @property (nonatomic, strong, readonly, nullable) DNode *preNode;
27 |
28 | /// 每次被移除的节点列表
29 | @property (nonatomic, strong, nullable) NSArray *removedNodes;
30 |
31 | /// 当前被显示的FlutterViewControllerID
32 | @property (nonatomic, copy, nullable) NSString *currentFlutterViewControllerID;
33 |
34 | + (instancetype)sharedInstance;
35 |
36 | + (instancetype)new NS_UNAVAILABLE;
37 | - (instancetype)init NS_UNAVAILABLE;
38 |
39 | /// 配置日志信息
40 | - (void)configLogFileWithDebugMode:(BOOL)debugMode;
41 |
42 | /// 清除本地日志
43 | - (void)cleanLogFile;
44 |
45 | /// 检查节点
46 | /// @param node 节点信息
47 | - (NSArray *)checkNode:(DNode *)node;
48 |
49 | /// 根据target从nodeLlist获取,倒序查找
50 | /// @param target target
51 | - (nullable DNode *)nodeWithTarget:(NSString *)target;
52 |
53 | /// 根据identifier从nodeLlist获取,倒序查找
54 | /// @param identifier identifier
55 | - (nullable DNode *)nodeWithIdentifier:(NSString *)identifier;
56 |
57 | /// 原生页面的pop返回手势能否响应
58 | /// 判断逻辑
59 | /// NodeList的最后一个节点就是当前页面正在显示的页面
60 | /// 取出最后一个节点,判断该节点的前面一个节点
61 | /// 如果前一个节点是Flutter页面,则原生页面的pop返回手势不能响应,否则可以响应
62 | - (BOOL)nativePopGestureCanReponse;
63 |
64 | /// 创建节点
65 | /// @param scheme 节点标识
66 | /// @param pageType 下一页面类型
67 | /// @param actionType 跳转类型
68 | /// @param params 附带参数
69 | - (DNode *)nextPageScheme:(NSString *)scheme
70 | pageType:(DNodePageType)pageType
71 | action:(DNodeActionType)actionType
72 | params:(nullable NSDictionary *)params;
73 |
74 | /// 应用生命周期消息
75 | /// @param state 应用的生命周期
76 | - (void)sendAppliccationLifeCicleToFlutter:(DStackApplicationState)state;
77 |
78 | /// 更新临界节点
79 | /// @param nodeInfo nodeInfo
80 | - (void)updateBoundaryNode:(NSDictionary *)nodeInfo;
81 |
82 | /// 更新根节点信息
83 | /// @param node node
84 | - (BOOL)updateRootNode:(DNode *)node;
85 |
86 | /// 获取日志文件内容
87 | - (nullable NSArray *)logFiles;
88 |
89 | @end
90 |
91 | NS_ASSUME_NONNULL_END
92 |
--------------------------------------------------------------------------------
/ios/Classes/Stack/DStackProvider.h:
--------------------------------------------------------------------------------
1 | //
2 | // DStackProvider.h
3 | // 定义
4 | //
5 | // Created by TAL on 2020/1/16.
6 | //
7 |
8 | #ifndef DStackProvider_h
9 | #define DStackProvider_h
10 |
11 | #import
12 |
13 | FOUNDATION_EXPORT void _dStackLog(NSString *msg, NSString *format, ...);
14 | #define DStackLog(format, ...) (_dStackLog(@"", format, ## __VA_ARGS__))
15 | #define DStackError(format, ...) (_dStackLog(@"!!!!!!!!! DstackError !!!!!!!!! ==> ", format, ## __VA_ARGS__))
16 |
17 | #define DStackInject(_className_) \
18 | class DStackInjectClass; \
19 | char * __DStackInject##_className_##Char \
20 | __attribute__ ((used, section("__DATA, __DStackEInject "))) = ""#_className_""
21 |
22 |
23 | #define DStackDeprecated(msg) __attribute__((deprecated(msg)))
24 |
25 |
26 | // 页面类型
27 | typedef NS_ENUM(NSInteger, DNodePageType) {
28 | DNodePageTypeUnknow,
29 | DNodePageTypeNative, // 原生页面
30 | DNodePageTypeFlutter, // Flutter页面
31 | };
32 |
33 | // 跳转类型
34 | typedef NS_ENUM(NSInteger, DNodeActionType) {
35 | DNodeActionTypeUnknow,
36 | DNodeActionTypePush, // push跳转
37 | DNodeActionTypePresent, // present跳转
38 | DNodeActionTypePop, // pop返回
39 | DNodeActionTypePopTo, // popTo返回
40 | DNodeActionTypePopToRoot, // popToRoot
41 | DNodeActionTypePopSkip, // dopSkip
42 | DNodeActionTypeGesture, // 手势
43 | DNodeActionTypeDismiss, // dismiss返回
44 | DNodeActionTypeReplace, // replace返回
45 | DNodeActionTypeDidPop, // didPop确认
46 | DNodeActionTypePushAndRemoveUntil, // pushAndRemoveUntil
47 | };
48 |
49 | // 应用的生命周期
50 | typedef NS_ENUM(NSInteger, DStackApplicationState) {
51 | DStackApplicationStateStart, // 应用启动
52 | DStackApplicationStateForeground, // 进入前台
53 | DStackApplicationStateBackground, // 进入后台
54 | };
55 |
56 |
57 | @protocol DStackPluginProtocol
58 |
59 | @required
60 | /// 处理Flutter发送至nnative的消息
61 | /// @param call call
62 | /// @param result result
63 | - (void)handleSendNodeToNativeMessage:(FlutterMethodCall*)call
64 | result:(FlutterResult)result;
65 |
66 | /// 处理flutter发送过来的移除节点信息
67 | /// @param call call
68 | /// @param result result
69 | - (void)handleRemoveFlutterPageNode:(FlutterMethodCall*)call
70 | result:(FlutterResult)result;
71 |
72 | /// 发送节点列表到flutter
73 | /// @param result result
74 | - (void)sendNodeListToFlutter:(FlutterResult)result;
75 |
76 | /// 发送homePageRoute
77 | /// @param call call
78 | - (void)sendHomePageRoute:(FlutterMethodCall *)call;
79 |
80 | /// 更新临界节点信息
81 | /// @param call call
82 | - (void)updateBoundaryNode:(FlutterMethodCall *)call;
83 |
84 | @end
85 |
86 | #endif /* DStackProvider_h */
87 |
--------------------------------------------------------------------------------
/lib/channel/dchannel.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * Created with Android Studio.
3 | * User: whqfor
4 | * Date: 2020-02-03
5 | * Time: 14:20
6 | * email: wanghuaqiang@tal.com
7 | * tartget: 处理通道相关
8 | */
9 |
10 | import 'dart:async';
11 |
12 | import 'package:d_stack/constant/constant_config.dart';
13 | import 'package:d_stack/navigator/dnavigator_manager.dart';
14 | import 'package:d_stack/observer/d_node_observer.dart';
15 | import 'package:d_stack/observer/life_cycle_observer.dart';
16 | import 'package:flutter/services.dart';
17 |
18 | import '../d_stack.dart';
19 |
20 | class DChannel {
21 | late MethodChannel _methodChannel;
22 |
23 | DChannel(MethodChannel methodChannel) {
24 | _methodChannel = methodChannel;
25 | _methodChannel.setMethodCallHandler((MethodCall call) {
26 | // sendActionToFlutter 处理Native发过来的指令
27 | if (DStackConstant.nodeToFlutter == call.method) {
28 | return DNavigatorManager.handleActionToFlutter(call.arguments)!;
29 | } else if (DStackConstant.lifeCycle == call.method) {
30 | return LifeCycleHandler.handleLifecycleMessage(call.arguments);
31 | } else if (DStackConstant.sendOperationNodeToFlutter == call.method) {
32 | return DNodeObserverHandler.handlerNodeMessage(call.arguments);
33 | }
34 | return Future.value();
35 | });
36 | }
37 |
38 | Future invokeMethod(String method, [dynamic arguments]) async {
39 | return _methodChannel.invokeMethod(method, arguments);
40 | }
41 |
42 | Future sendNodeToNative(Map arguments) async {
43 | assert(arguments != null);
44 | return _methodChannel.invokeMethod(DStackConstant.nodeToNative, arguments);
45 | }
46 |
47 | Future sendRemoveFlutterPageNode(Map arguments) async {
48 | assert(arguments != null);
49 | return _methodChannel.invokeMethod(DStackConstant.checkRemoved, arguments);
50 | }
51 |
52 | Future> getNodeList() async {
53 | return _methodChannel
54 | .invokeMethod(DStackConstant.nodeList, null)
55 | .then((list) {
56 | if (list is List) {
57 | List nodeList = [];
58 | list.forEach((element) {
59 | DStackNode node = DStackNode(
60 | route: element["route"], pageType: element["pageType"]);
61 | nodeList.add(node);
62 | });
63 | return Future.value(nodeList);
64 | }
65 | return Future.value([]);
66 | });
67 | }
68 |
69 | Future sendHomePageRoute(String? route) {
70 | return _methodChannel.invokeMethod(
71 | DStackConstant.sendHomePageRoute, {"homePageRoute": route});
72 | }
73 |
74 | /// 发送更新临界节点的信息
75 | Future sendUpdateBoundaryNode(Map params) {
76 | return _methodChannel.invokeMethod(
77 | DStackConstant.sendUpdateBoundaryNode, params);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/navigator/node_entity.dart:
--------------------------------------------------------------------------------
1 | /*
2 | * Created with Android Studio.
3 | * User: linkewen
4 | * Date: 2020/12/3
5 | * Time: 17:18
6 | * target: node节点描述
7 | */
8 |
9 | import 'package:d_stack/d_stack.dart';
10 |
11 | class DNodeEntity {
12 | /// 节点列表
13 | late List nodeList;
14 |
15 | /// 跳转类型
16 | String? action;
17 |
18 | /// 是否有转场动画
19 | bool? animated;
20 |
21 | DNodeEntity.fromJson(Map json) {
22 | if (json["nodes"] != null) {
23 | final List list = [];
24 | (json["nodes"] as List).forEach((element) {
25 | list.add(DNode.fromJson(element));
26 | });
27 | nodeList = list;
28 | action = json["action"] ?? "";
29 | animated = json["animated"] ?? true;
30 | }
31 | }
32 |
33 | Map toJson() {
34 | final Map json = Map();
35 | List