美文网首页
Flutter混合开发实践

Flutter混合开发实践

作者: 游侠_6fb7 | 来源:发表于2019-03-25 09:58 被阅读0次

Flutter集成页面效果图

a20190327194644.jpg

集成

20190328130657.jpg

Gradle升级

1、buildTools gradle升级到3.0.1
加快编译速度,已经编译过的无需重新再编译,编译总时间,是以前的一半;
2、Gradle 环境升级到4.1
Flutter依赖gradle环境3.0.1以上;
3、升级gradle后lib模块中没有monkey,debugProguard
buildType时,兼容使用debug
//如:
debugProguard {
matchingFallbacks = ['debug']
}
4、git升级到2.0以上
如果不升级,执行flutter packages get会报如下错误:
The current Flutter SDK version is 0.0.0-unknown.
Because flutter requires Flutter SDK version >=0.1.4 <2.0.0, version solving failed.
Flutter SDK version.dart会判断git版本,升级git到2.0问题解决;

Flutter页面及混合栈管理

 引入Flutter之后,我们首要面临的问题便是混合栈的管理。如我们首先实践的是向导页,则有一个常见的应用场景:产品详情页->向导页->向导详情页-->分享界面(右上角底部弹层)。如何去解决这种Native 与Flutter任意嵌套的问题呢?

1、每个页面有个Activity,保证页面逻辑正常工作;
2、Flutter和Native页面直接正常通讯,共享数据;
3、Native页面可任意呼起Flutter页面,Flutter页面可正常呼起Native页面
4、用户体验无差异

为了解决这些问题,设计如下:

1、所有的Flutter页面复用一个FlutterActivity;


Flutter_类图.png

restoreBundle 负责路由参数解析
TNFlutterEvent 负责Bridege通讯
mComponentName Flutter页面名称
mComponentParams 页面参数
base里公用Natvie中打点及设置等;
2、每个Flutter页面都有一个Activity,通过mComponentName区分不同页面,通过参数传递进入到对应的的flutterPage;
3、Flutter Page调用Bridge通过OpenUrl路由解析,任意呼起页面;
4、所有的页面跳转和动画都通过Native实现
因为原生(iOS/Android)自带跳转动画,而Flutter内部跳转也自带动画,为了用户体验,Flutter内部跳转(push/pop)相关动画,统一由Native接管,这样用户就感受不到差异。
5、混合栈管理流程图


Flutter控制流程图.png

通讯方式:

1.Flutter调用Native
Flutter端:

static dynamic setOpenUrl(url) async {
  if (url == null) {
    return null;
  }
  Map<String, String> map = new Map();
  map['url'] = url;
  try {
    var result = await platform.invokeMethod('resolveUrl', map);
    return result;
  } on PlatformException catch (e) {
    print("---->" + e.message);
  }
  return null;
}

Native端

@Override
public void onMethodCall(MethodCall call, Result result) {
    //onMain Thread
    LogUtils.i(TAG, "call native method {}:--arguments-----{}---->", call.method, call.arguments);
    // 在这个回调里处理从Flutter来的调用
    testSuccessful = call.method.equals("success");
    testFinished.open();
    invokeMethod(call, result);
}
 
 
private void invokeMethod(MethodCall call, Result result) {
    try {
        Method method = FlutterBridge.class.getMethod(call.method, Activity.class, Object.class, Result.class);
        method.invoke(null, mActivity, call.arguments, result);
    } catch (IllegalAccessException e) {
        FlutterBridgeUtil.invokeErrorCallback(result, RNConstant.ErrorCode.NOT_FOUND);
    } catch (InvocationTargetException e) {
        FlutterBridgeUtil.invokeErrorCallback(result, RNConstant.ErrorCode.NOT_FOUND);
    } catch (NoSuchMethodException e) {
        FlutterBridgeUtil.invokeErrorCallback(result, RNConstant.ErrorCode.NOT_FOUND);
    }
}

2.Native调用Flutter
Flutter端

static const EventChannel _eventChannel =
    const EventChannel('com.tuniu.app.ui/stream');
 
void listenNativeEvent() {
  _eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
}
 
void _onEvent(Object event) {
  //print("Battery status: ${event == 'charging' ? '' : 'dis'}charging.");
  print('---_onEvent---11->' + jsonEncode(event));
  String str = jsonEncode(event);
  setState(() {
    _batteryLevel = 'level at $str';
  });
}
 
void _onError(Object error) {
  print('---_onError---11->' + 'Battery status: unknown.');
  String str = jsonEncode(error);
  setState(() {
    _batteryLevel = 'level at 1 $str';
  });
}
 
@override
void initState() {
  super.initState();
  listenNativeEvent();
}

Native端

public TNFlutterEvent(FlutterView flutterView) {
    //添加广播通知
    final EventChannel eventChannel = new EventChannel(flutterView, TNFlutterMethodCall.STREAM);
    eventChannel.setStreamHandler(this);
    EventBus.getDefault().register(this);
}
 
/**
 * 监听登录结果
 */
public void onEvent(LoginEvent loginEvent) {
    if (loginEvent != null) {
        LogUtils.i(TAG, "send event: {}, params: {}", RNConstant.RNEventConstant.EVENT_NAME_LOGIN_STATUS_CHANGED, JsonUtils.encode(loginEvent));
        // 把状态发给Flutter
        if (mEvents != null) {
            mEvents.success(JsonUtils.encode(loginEvent));
        }
    }
}
 
 
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
    LogUtils.i(TAG, "onListen------>");
    if (eventSink != null) {
        this.mEvents = eventSink;
    }
}
 
@Override
public void onCancel(Object o) {
 
}
 
/**
 * 接收eventbus 事件
 *
 * @param notify 参数供回调
 */
public void onEvent(NotificationRequest notify) {
    // 把状态发给Flutter
    if (mEvents != null) {
        mEvents.success(notify);
    }
 
}
 
public void onDestory() {
    EventBus.getDefault().unregister(this);
    mEvents = null;
}

图片加载

1、图片缓存
无法和Native公用一套缓存图片框架,采用
cached_network_image 框架
2、支持webp,gif等图片格式,支持本地图片

内存,CPU占用

Flutter向导页面

f20190327194730.jpg

RN向导页面

r20190327195301.jpg

Flutter,RN性能对比
测试环境,华为荣耀6,系统版本:6.0


20190327202303.jpg

FPS流畅度,暂未采集,从肉眼观察,比RN流畅

布局

20190327200958.jpg

向导页整体结构
主题风格,滑动,吸顶,tab切换,上拉加载,下拉刷新

相关文章

网友评论

      本文标题:Flutter混合开发实践

      本文链接:https://www.haomeiwen.com/subject/acgmvqtx.html