Coder Social home page Coder Social logo

hybrid_stack_manager's Introduction

hybrid_stack_manager

In hybrid scenarios where there are flutter pages and native pages, and they can jump to flutter/native at will. In other words, hybrid stack management would be the first important problem we should consider. This package can manage the hybrid stack and supports any jumping between flutter/native and native/flutter.

Architecture

Snapshot

iOS

hybrid_stack_management_ios

Android

hybrid_stack_management_android

Usage

Add dependency in pubspec.yaml:

hybrid_stack_manager:0.0.6

After getting the package using "flutter packages get",you can check the examples within the package to see how to use it.

Usage in iOS side

1.Construct a navigationController as the rootWindow's rootViewController for later use when pushing.

2.Set the XURLRouter's nativeOpenUrlHandler where you can implement your own business related router logic,as below:

    [[XURLRouter sharedInstance] setNativeOpenUrlHandler:^UIViewController *(NSString *url,NSDictionary *query,NSDictionary *params){
        NSURL *tmpUrl = [NSURL URLWithString:url];
        if([@"ndemo" isEqualToString:tmpUrl.host]){
            return [XDemoController new];
        }
        return nil;
    }];
  1. All scheme's query will be checked whehter to jump Flutter(flutter=true) or Native(flutter=false/nil)。 This is a universal logic applying in ios/android/flutter. As below:
void XOpenURLWithQueryAndParams(NSString *url,NSDictionary *query,NSDictionary *params){
    NSURL *tmpUrl = [NSURL URLWithString:url];
    UINavigationController *rootNav = (UINavigationController*)[UIApplication sharedApplication].delegate.window.rootViewController;
    if(![kOpenUrlPrefix isEqualToString:tmpUrl.scheme])
        return;
    if([[query objectForKey:@"flutter"] boolValue]){
        [[XFlutterModule sharedInstance] openURL:url query:query params:params];
        return;
    }
    NativeOpenUrlHandler handler = [XURLRouter sharedInstance].nativeOpenUrlHandler;
    if(handler!=nil)
    {
        UIViewController *vc = handler(url,query,params);
        if(vc!=nil)
            [rootNav pushViewController:vc animated:YES];
    }
}

Usage in Android side

1.Set the XURLRouter's appContextcontext with the ApplicationContext for later use when jumping.

XURLRouter.sharedInstance().setAppContext(getApplicationContext());

2.Set XURLRouter's NativeRouterHandler with one always existing instance. This instance should implements XURLRouterHandler and implement method:openUrlWithQueryAndParams where you can implement your own business related router logic,as below:

  void setupNativeOpenUrlHandler(){
    XURLRouter.sharedInstance().setNativeRouterHandler(this);
  }
  public Class openUrlWithQueryAndParams(String url, HashMap query, HashMap params){
    Uri tmpUri = Uri.parse(url);
    if("ndemo".equals(tmpUri.getHost())){
      return XDemoActivity.class;
    }
    return null;
  }

Usage in Flutter side

1.Init a global key for later use to fetch a context and pass it to the Router. 2.Set the Router's routerWidgetHandler where Flutter side router logic is implemented,as below:

    Router.sharedInstance().routerWidgetHandler =
        ({RouterOption routeOption, Key key}) {
      if (routeOption.url == "hrd://fdemo") {
        return new FDemoWidget(routeOption, key: key);
      }
      return null;
    };
    return _singleton;

Attention

1.In Flutter,the NavigatorState class located in flutter/lib/src/widgets/navigator.dart is modified by adding a getter function to fetch the history as below:

  List<Route<dynamic>> get history => _history;

2.In iOS,I reuse the XFlutterViewController singleton which is embedded in FlutterViewWrapperController with the help of addChildVC/removeFromParentVC。It is necessary to ensure that the viewWill/DidAppear/Disappear call could be passed from ParentVC Appear to ChildVC(Especially the viewWillAppear: and viewDidDisappear:)。

- (BOOL)shouldAutomaticallyForwardAppearanceMethods{
    return TRUE;
}

3.Environment

KyleWongdeMacBook-Pro:ios kylewong$ /Users/kylewong/Codes/Flutter/official/flutter/bin/flutter doctor -v
[✓] Flutter (Channel unknown, v0.6.0, on Mac OS X 10.14 18A365a, locale en-CN)
    • Flutter version 0.6.0 at /Users/kylewong/Codes/Flutter/official/flutter
    • Framework revision 9299c02cf7 (5 days ago), 2018-08-16 00:35:12 +0200
    • Engine revision e3687f70c7
    • Dart version 2.1.0-dev.0.0.flutter-be6309690f

[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
    • Android SDK at /Users/kylewong/Library/Android/sdk
    • Android NDK at /Users/kylewong/Library/Android/sdk/ndk-bundle
    • Platform android-27, build-tools 27.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
    • All Android licenses accepted.

[!] iOS toolchain - develop for iOS devices (Xcode 9.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 9.4.1, Build version 9F2000
    • ios-deploy 1.9.2
    ! CocoaPods out of date (1.5.0 is recommended).
        CocoaPods is used to retrieve the iOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without resolving iOS dependencies with CocoaPods, plugins will not work on iOS.
        For more info, see https://flutter.io/platform-plugins
      To upgrade:
        brew upgrade cocoapods
        pod setup

[✓] Android Studio (version 3.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 26.0.1
    • Dart plugin version 173.4700
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)

[!] VS Code (version 1.25.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected devices (1 available)
    • Nexus 5X • 00d25786e6b71602 • android-arm64 • Android 8.1.0 (API 27)

Though flutter beta v0.6.0 is used in my environment. In fact, this hybrid stack management logic works even in v0.3.1 and above.

Contact me

Contact me

hybrid_stack_manager's People

Contributors

kangwang1988 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

hybrid_stack_manager's Issues

flutter页面跳转至原生或flutter均失败(on Android)

flutter页面跳转至原生或flutter均失败;
原生调整至flutter 报错:
java.lang.NoSuchFieldException: No field mDiscoveryReceiver in class Lio/flutter/view/FlutterView; (declaration of 'io.flutter.view.FlutterView' appears in /data/app/com.yqxue.yqxue-LwHUtsZoy3_l_HqkhfarfQ==/base.apk:classes20.dex)
at java.lang.Class.getDeclaredField(Native Method)
02-21 20:37:03.002 11210-11210/com.yqxue.yqxue W/System.err: at com.taobao.hybridstackmanager.XFlutterView.registerReceiver(XFlutterView.java:33)
at com.taobao.hybridstackmanager.FlutterWrapperActivity.onCreate(FlutterWrapperActivity.java:126)
at android.app.Activity.performCreate(Activity.java:7040)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2809)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2931)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1620)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:173)
at android.app.ActivityThread.main(ActivityThread.java:6698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
02-21 20:37:03.003 11210-11210/com.yqxue.yqxue W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)

请问如果是 UITabbarController 怎么办

Navigation跳转的话没什么问题,如果是TabbarController的话,假如我两个Tab下是两个Flutter的页面,来回切换的时候Flutter内部的页面也要联动吧?

nativeOpenUrlHandler 无法赋值

查看了一下XURLRouter的源码,nativeOpenUrlHandler使用了weak而不是copy,导致给nativeOpenUrlHandler赋值后nativeOpenUrlHandler的值立刻变成nil。

[ios] after flutter page to flutter page, page cann't refresh by setState

after flutter page to flutter page, page cann't refresh by setState.

after setState, the build method has been called, but the page ui not change.

在flutter页面通过HybridStackManagerPlugin.hybridStackManagerPlugin.openUrlFromNative 跳转到另一个flutter页面之后,StatefulWidget页面不能通过setState刷新,页面动画也不能播放了。
ios上有这个问题,android正常。

The getter 'history' isn't defined for the class '#lib1::NavigatorState'.

61:48: Error: The getter 'history' isn't defined for the class '#lib1::NavigatorState'.
compiler message: Try correcting the name to the name of an existing getter, or defining a getter or field named 'history'.
compiler message: List<Route> navHistory = navState.history;

Is there a way to solve this problem?

image

关于传递参数?

android中

        HashMap<String, Object> m = new HashMap<>();
        m.put("flutter", true);
        HashMap<String, Object> params = new HashMap<>();
        params.put("stationName", stationName);
        params.put("stationId", stationId);
        XURLRouter.sharedInstance().openUrlWithQueryAndParams("hrd://equipList", m, params);

flutter中

EquipList(RouterOption option, {Key key}) : super(key: key) {
    routeOption = option;
    var map = routeOption.params;
    print("====================" + map.length.toString());
  }

debug的时候,看到flutter中跳转过来了,routeOption中只看到url,params和 query的 size都是 0
请问下传值这个应该怎么处理呢?
另外 m.put("flutter", true); 这个是固定写法吗

hybrid_stack_manager/HybridStackManager.h

'hybrid_stack_manager/HybridStackManager.h' file not found

flutter

➜  .ios git:(master) ✗ flutter --version
Flutter 1.1.6-pre.11 • channel master • https://github.com/flutter/flutter.git
Framework • revision 53727866e6 (23 hours ago) • 2019-01-03 12:05:53 +0700
Engine • revision 844c3274e6
Tools • Dart 2.1.1 (build 2.1.1-dev.0.1 88e6fe0f67)

pod

➜  .ios git:(master) ✗ pod --version
1.4.0

history not exist

Dart Error: Unhandled exception:
'package:hybrid_stack_manager/router.dart': error: line 118 pos 48: file:///Users/dengjinlong/Documents/5-Flutter/hybrid_stack_manager/lib/router.dart:118:48: Error: The getter 'history' isn't defined for the class '#lib1::NavigatorState'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'history'.
List<Route> navHistory = navState.history;
^
List<Route> navHistory = navState.history;
^

History not exist

Even after adding List<_RouteEntry> get history => _history;
in Navigator State class... An error " A value of type 'List<_RouteEntry>' can't be assigned to a variable of type 'List<Route>" is thrown.
Please guide.

Flutter version is 1.20.1

求帮助,导入项目运行就会报错

file:///D:/Environment/flutter_windows_v1.2.1-stable/flutter/packages/flutter/lib/src/widgets/navigator.dart:2091:9: Error: The getter 'SchedulerBinding' isn't defined for the class 'NavigatorState'.

  • 'NavigatorState' is from 'package:flutter/src/widgets/navigator.dart' ('file:///D:/Environment/flutter_windows_v1.2.1-stable/flutter/packages/flutter/lib/src/widgets/navigator.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'SchedulerBinding'.
    if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.idle) {

Have you ever met problem when click the home key?

I run your example app , but i find a problem there.

  1. Enter example app
  2. Click the button to jump to flutter
  3. Click the home key , then click the Launcher Icon to enter app from the Desk
  4. I see Native Root Page
    Can't keep the page state?

java.lang.NoSuchFieldException: No field mDiscoveryReceiver in class Lio/flutter/view/FlutterView

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v0.8.2, on Mac OS X 10.13.6 17G65, locale zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 10.0)
[✓] Android Studio (version 3.1)
[✓] VS Code (version 1.23.1)
[✓] Connected devices (1 available)

• No issues found!

Warnings:

W/System.err(15362): java.lang.NoSuchFieldException: No field mDiscoveryReceiver in class Lio/flutter/view/FlutterView; (declaration of 'io.flutter.view.FlutterView' appears in /data/app/com.example.hybridstackmanagerexample-2/base.apk)
W/System.err(15362): at java.lang.Class.getDeclaredField(Native Method)
W/System.err(15362): at com.taobao.hybridstackmanager.XFlutterView.registerReceiver(XFlutterView.java:33)
W/System.err(15362): at com.taobao.hybridstackmanager.FlutterWrapperActivity.onCreate(FlutterWrapperActivity.java:136)
W/System.err(15362): at android.app.Activity.performCreate(Activity.java:6915)
W/System.err(15362): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
W/System.err(15362): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2746)
W/System.err(15362): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2864)
W/System.err(15362): at android.app.ActivityThread.-wrap12(ActivityThread.java)
W/System.err(15362): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567)
W/System.err(15362): at android.os.Handler.dispatchMessage(Handler.java:105)
W/System.err(15362): at android.os.Looper.loop(Looper.java:156)
W/System.err(15362): at android.app.ActivityThread.main(ActivityThread.java:6523)
W/System.err(15362): at java.lang.reflect.Method.invoke(Native Method)
W/System.err(15362): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
W/System.err(15362): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
I/System.out(15362): In new implementation for FlutterPluginRegistry,AssertionError is thrown when try to attach twice, it doesn't matter even we ignore it.
I/HwPointEventFilter(15362): do not support AFT because of no config

I jump native(MainActivity) to flutter,but can not jump back.

01-01 09:45:55.374 14183-14183/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.greentownit.parkmanagement, PID: 14183
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
at android.app.ContextImpl.startActivity(ContextImpl.java:734)
at android.app.ContextImpl.startActivity(ContextImpl.java:721)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:345)
at com.taobao.hybridstackmanager.XURLRouter.openUrlWithQueryAndParams(XURLRouter.java:38)
at com.greentownit.parkmanagement.ui.MainActivity$1.onClick(MainActivity.java:39)
at android.view.View.performClick(View.java:5697)
at android.widget.TextView.performClick(TextView.java:10814)
at android.view.View$PerformClick.run(View.java:22526)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

编译错误,,请教大神如何解决?

f06f16c4-73d8-4cd8-b718-43d8752142c2

file:///Users/zhouyang/StudioProjects7/hybrid_stack_manager/lib/router.dart:85:48: Error: The getter 'history' isn't defined for the class '#lib1::NavigatorState'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'history'.
List<Route> navHistory = navState.history;

flutterview backpress doesnt work(on android)

in my first flutter view demo page, i meet this issue that back press key doesn't work.
detail info:
in FlutterWrapperActivity:tryPopCurActivity, only when flutterWrapperInstCnt> 1, activity can be finished. If user press backkey to navigator to native activity, it doesn't work.
if i modify "flutterWrapperInstCnt> 1," to "flutterWrapperInstCnt> 0", it does work well.
why here is "flutterWrapperInstCnt> 1,", is it an issue?
thanks
@OverRide
public void tryPopCurActivity() {
if(flutterWrapperInstCnt>1){
finish();
saveFinishSnapshot(true);
}
}

Failed to resolve:com.taobao.hybridstackmanager:hybrid_stack_manager:1.0.1-SNAPSHOT

我是先在自己的flutter_module里加入你的插件hybridstackmanager0.0.6。然后将集成插件的flutter_module打包成一个aar,最终把这个aar集成进现有的项目。
但是在项目依赖aar时,抛出错误:
Failed to resolve:com.taobao.hybridstackmanager:hybrid_stack_manager:1.0.1-SNAPSHOT
看了下打成aar后,插件项目里写死了1.0.1-SNAPSHOT版本。可是maven仓库里找不到...

The getter 'history' isn't defined for the class 'NagigatorState'

image

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master,v0.5.8, on Mac OS X 10.13.4 17E199, locale zh-Hans-CN)
[!] Android toolchain - develop for Android devices (Android SDK 27.0.3)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[!] iOS toolchain - develop for iOS devices (Xcode 9.4)
✗ libimobiledevice and ideviceinstaller are not installed. To install, run:
brew install --HEAD libimobiledevice
brew install ideviceinstaller
✗ ios-deploy not installed. To install:
brew install ios-deploy
[✓] Android Studio (version 3.0)
[✓] Connected devices (1 available)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.