Flutter 混合開發實戰問題記錄(二)自定義簡單的混合棧路由

混合開發中不可避免的存在native向flutter頁面跳轉,flutter向原生跳轉,甚至Activity或Fragment中某個view使用flutter開發。 鹹魚技術團隊做爲國內flutter技術領跑者開源了其混合棧的工具。 簡書文章,或能夠直接查閱GitHub倉庫.android

鑑於hyBirdStacManager中含有一些咱們不很須要的功能和若干bug,目前咱們能夠借鑑下思路寫個簡單的工具類。git

1、flutter -> native

flutter開啓原生頁面並傳參較爲簡單,能夠經過官方methodChannel直接調用native方法,不在贅述github

dart代碼

class MyFlutterPlugin {
    static const MethodChannel _channel =
      const MethodChannel('com.your.packagename/flutter_plugin');
    
     /**
   * 打開原生頁面
   */
    static Future<String> openNativePage(String target , {Map paramsMap}) async {
     if(paramsMap == null){
        paramsMap = Map();
     }
     return await _channel.invokeMethod("openNative" , {"target" :target , "params" : paramsMap});
  }
}
複製代碼

參數的形式能夠自定義爲json,object等等json

android端代碼

註冊插件的時機跟你的狀況而定,如今先放在自動生成的插件後邊bash

public abstract class BaseFlutterActivity extends FlutterFragmentActivity implements         LifecycleOwner{

      ......    

      @Override
    protected void onCreate(Bundle savedInstanceState) {
        AppManager.getAppManager().addActivity(this);
        ......
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);
        //自定義plugin
        MyPlugin.registerWith(getFlutterView());
    }
}

public class MyPlugin {

    public static void registerWith(final BinaryMessenger messenger){
        new MethodChannel(messenger, "com.your.packagename/flutter_plugin").setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
            
                ....
                
                // 解析參數,作頁面跳轉
                if ("openNative".equals(methodCall.method)){
                    NativeRouteUtil.schemePage(methodCall,result);
                }
            }
        });
    }
}

跳轉代碼可參考僞代碼

 public static void schemePage(MethodCall methodCall, MethodChannel.Result result) {
       
        String target = methodCall.argument("target");
        switch (target) {
            case FlutterConstant.ROUTE_NATIVE_SETTING:
                SettingActivity.openSettingActivity(context);
                break;
            default:
                break;
        }
    }

複製代碼

2、native -> flutter

這是很容易想到的思路,爲了保證界面跳轉動畫統一,頁面棧方便維護(即便是flutter棧),在每次渲染一個新flutter頁面的時候給他一個原生的載體,即一個Activity的殼,在Activity中的flutterView加載flutter頁面框架

dart代碼

flutter中有個main()方法入口,而且官方爲咱們提供了入口route的獲取方式less

void main(){
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((_){
    runApp(new MyApp());
  });
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home:  _widgetForRoute(window.defaultRouteName),
    );
  }
}

Widget _widgetForRoute(String route) {
  String uri = StringUtil.getSchemeRouteName(route);
  String paramsJson = StringUtil.getSchemeRouteParams(route);
  switch (uri) {
    case ROUTE_ABOUT_US:
      return  AboutWidget(params: paramsJson);

    default:
      Toast.toast("您訪問的頁面不存在");
      SystemNavigator.pop();
  }
}

複製代碼

_widgetForRoute(String route)方法的參數能夠自行配置標準,能夠爲/path + ?+ params的形式,標記進入哪一個頁面和傳遞相應參數。async

android端代碼

套殼是常見的封裝形式,舉個簡單的例子,ide

public class FlutterContainerActivity extends BaseFlutterActivity {

    public static void openFlutterContainerAct(Context context, String url) {
        try {
            Intent intent = new Intent(context, FlutterContainerActivity.class);
            intent.putExtra(ROUTE_TARGET,url);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.setAction(ROUTE_ACTION);
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
複製代碼

3、native -> native

略.工具

不過能夠封裝一下,進入你的框架內,做爲routeUtil的一部分

4、flutter -> flutter

雖然flutter內部有官方的跳轉方法,但假如你的根flutter頁面做爲tab嵌入的方式渲染的話,若是用 Navigator.of(context)跳轉,會發生新頁面沒法全屏的現象,因此仍是爲了動畫統一和頁面的良好管理機制,仍然推薦在dart內部先調用plugin方法,而後再用方式二進行跳轉。

附dart內部的route跳轉

class RouterUtil {

  static const ROUTE = 1;
  static const FADE = 2;

  static route(BuildContext context, Widget targetWidget) {
    Navigator.of(context)
        .push(MaterialPageRoute(builder: (mContext) => targetWidget));
  }

  static routeAnimation(BuildContext context, Widget targetWidget) {
    Navigator.of(context)
        .push(_MyCustomRoute(builder: (context) => targetWidget));
  }

  static route4Animation(BuildContext context, Widget targetWidget , num type) {
    Navigator.of(context)
        .push(_MyCustomRoute(builder: (context) => targetWidget , type : type));
  }
}

class _MyCustomRoute<T> extends MaterialPageRoute<T> {

  num mType = 2;

  _MyCustomRoute({WidgetBuilder builder, RouteSettings settings , var type})
      : super(builder: builder, settings: settings);

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    if (settings.isInitialRoute) return child;
    if(mType == 1){
      return RotationTransition(turns: animation, child: child);
    }else if(mType == 2){
      return FadeTransition(opacity: animation, child: child);
    }
    return FadeTransition(opacity: animation, child: child);
  }
}
複製代碼

前兩天閒魚放棄了以前的混合棧項目,新開源了flutter_boost , 這是github,有興趣能夠參考。

相關文章
相關標籤/搜索