flutter相关
2019-01-21 本文已影响91人
34sir
是什么?
谷歌的跨平台的移动UI框架 语言是dart(语法类似js)
官网
优势
- 性能
直接在两个平台上重写了各自的UIKit 减少了UI层的多层转换(相对于RN等) ;
AOT编译代码 - 路由
框架本身支持路由 - 兼容性
不依赖css等外部解释器 不存在兼容性问题(相对于RN等) - 热重载
UI层开发效率高
可行性
接入已有项目
image.pngandroid这边主要注意gradle版本的问题 后续有需要会有个详细的接入文档
和原生交互
注册插件
EventChannel
: 原生通知Dart
MethodChannel
: Dart
通知原生
例如如何调用现有的网络框架并且展示数据?
- 客户端(Android)
1⃣️ FlutterView关联Activity
flutterView = Flutter.createView(
DeferActivity.this,
lifecycle,
"route1"
);
addContentView(flutterView, layout);
2⃣️ 客户端注册通知Dart的回调
new EventChannel(flutterView, "samples.flutter.io/charging").setStreamHandler(
new EventChannel.StreamHandler() {
@Override
// 这个onListen是Flutter端开始监听这个channel时的回调,第二个参数 EventSink是用来传数据的载体。
public void onListen(Object arguments, EventChannel.EventSink events) {
eventSink=events;
}
@Override
public void onCancel(Object arguments) {
}
}
);
3⃣️客户端注册监听Dart的回调
private MethodChannel batteryChannel;
private void initBatteryChannel(){
eventSink.success("changeState");
if(batteryChannel==null){
batteryChannel=new MethodChannel(flutterView, "samples.flutter.io/battery");
}
batteryChannel.setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
// 在这个回调里处理从Flutter来的调用
if(call.method.equals("dataInteraction")){
if(!TextUtils.isEmpty(jsonString)){
result.success(jsonString);
}
}
}
});
}
- Dart
static const EventChannel eventChannel = const EventChannel('samples.flutter.io/charging');
eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);
void _onEvent(Object event) {
_dataInteraction();
}
static const platform = const MethodChannel('samples.flutter.io/battery');
Future<Null> _dataInteraction() async {
try {
var result = await platform.invokeMethod('dataInteraction', '123');
data =jsonDecode(result);
for (int i = 0; i < data.length; i++) {
widgets.add(getRow(i));
}
setState(() {
});
} on PlatformException catch (e) {}
}
页面框架
统一的Activity承载FlutterView 通过路由标识区分跳转
flutterView = Flutter.createView(
DeferActivity.this,
lifecycle,
"route1"
);
页面回退
Override
public void onBackPressed() {
if(this.flutterView!=null){
this.flutterView.popRoute(); //popRoute退出当前页面
}else {
super.onBackPressed();
}
}
import 'dart:ui';
void main() => runApp(_widgetForRoute(window.defaultRouteName));
Widget _widgetForRoute(String route){
switch(route){
case 'route1':
return new MyApp();
}
}
iOS端接入
AppDelegate的改造
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
@interface AppDelegate : FlutterAppDelegate
@property (nonatomic,strong) FlutterEngine *flutterEngine;
@end
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> // Only if you have Flutter Plugins
#include "AppDelegate.h"
@implementation AppDelegate
// This override can be omitted if you do not have any Flutter Plugins.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.flutterEngine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil];
[self.flutterEngine runWithEntrypoint:nil];
[GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
#import <Flutter/Flutter.h>
#import "AppDelegate.h"
#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:@selector(handleButtonAction)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"Press me" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blueColor]];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
}
- (void)handleButtonAction {
FlutterEngine *flutterEngine = [(AppDelegate *)[[UIApplication sharedApplication] delegate] flutterEngine];
FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
[flutterViewController setInitialRoute:@"route1"];
[self presentViewController:flutterViewController animated:false completion:nil];
}
@end
Flutter和原生平台的交互
- (void)doPressedBtn:(UIButton *)sender {
FlutterViewController *flutterViewController = [[FlutterViewController alloc] init];
flutterViewController.view.backgroundColor = [UIColor cyanColor];
[flutterViewController setInitialRoute:@"route2"];
[self configParamWith:flutterViewController];
[self presentViewController:flutterViewController animated:YES completion:nil];
}
- (void)configParamWith:(FlutterViewController *)viewController {
FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
methodChannelWithName:@"samples.flutter.io/battery"
binaryMessenger:viewController];
__weak typeof(self) weakSelf = self;
[batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
if ([@"getBatteryLevel" isEqualToString:call.method]) {
int batteryLevel = [weakSelf getBatteryLevel];
NSLog(@"%d",[NSThread isMainThread]);
if (batteryLevel == -1) {
result([FlutterError errorWithCode:@"UNAVAILABLE"
message:@"Battery info unavailable"
details:nil]);
} else {
result(@(batteryLevel));
}
} else {
result(FlutterMethodNotImplemented);
}
}];
}
- (int)getBatteryLevel {
return arc4random();
}
代码管理
Dart部分统一管理 两端共享
面临的问题
1⃣️ 组合的概念 需要适应
2⃣️ api较难上手
3⃣️ 项目中的夜间模式