• 差异点:

在Android中,View是屏幕上显示的所有内容的基础, 按钮、工具栏、输入框等一切都是View。 

iOS 构建 UI 的过程中将大量使用 view 对象。这些对象都是 UIView 的实例。它们可以用作容器来承载其他的 UIView,最终构成你的界面布局。

Flutter中,View相当于是Widget。然而,与View相比,Widget有一些不同之处。 首先,Widget仅支持一帧,并且在每一帧上,Flutter的框架都会创建一个Widget实例树(译者语:相当于一次性绘制整个界面)。 相比之下,在Android上View绘制结束后,就不会重绘,直到调用invalidate时才会重绘。

与Android的视图层次系统不同(在framework改变视图),而在Flutter中的widget是不可变的,这允许widget变得超级轻量

 

  • 更新视图:

Android中,直接改变View来更新视图,

iOS中的 views 在改变时并不会被重新创建。但是与其说 views 是可变的实例,不如说它们被绘制了一次,并且直到使用 setNeedsDisplay() 之后才会被重新绘制。

Flutter的widget是唯一的不变的(使得每一个widget都是非常轻量级),所以flutter不会直接更新,而必须使用Widget的状态(StatefullWidget和StatelessWidget)。

 注:StatelessWidget和StatefullWidget,自定义Widget都是选择继承这两者之一。

StatelessWidget面向那些始终不变的UI控件,比如标题栏中的标题;而StatefulWidget则是面向可能会改变UI状态的控件,比如有点击反馈的按钮。

StatefulWidget的创建需要指定一个State,在需要更新UI的时候调用setState(VoidCallback fn),并在VoidCallback中改变一些变量数值等,组件会重新build以达到刷新状态也就是刷新UI的效果。

  • 界面布局:

Android中您通过XML编写布局,

  • iOS中,与两者都不同,iOS可以通过用 Storyboard 文件来组织 views,并对它们设置约束,或者,你可能在 view controller 中使用代码来设置约束;

    Flutter中,您可以使用widget树来编写布局。

  • 注:State的生命周期有四种状态:

    created:当State对象被创建时候,State.initState方法会被调用;

    initialized:当State对象被创建,但还没有准备构建时,State.didChangeDependencies在这个时候会被调用;

    ready:State对象已经准备好了构建,State.dispose没有被调用的时候;

    defunct:State.dispose被调用后,State对象不能够被构建

  • 如何在布局中添加或删除组件:

在Android中从父级控件调用addChild或removeChild以动态添加或删除View;

iOS中,在父view中调用addSubView()或在子view中调用removeFromSuperview()来动态的添加或删除子views;

Flutter中widget是唯一不变的,所以widget是只有继承StatefullWidget,并由其父类来根据传入的值进行widget的切换以及状态的改变(同上的更新视图)。

  • 动画处理:

在Android中可以通过View.animate()对视图进行动画处理;

iOS中调用 animate(withDuration:animations:) 方法来给一个 view 创建动画

Futter中通过动画库给widget添加动画;

注:在Android中,您可以通过XML创建动画或在视图上调用.animate()。在Flutter中,您可以将widget包装到Animation中;与Android相似,在Flutter中,您有一个AnimationController和一个Interpolator, 它是Animation类的扩展,例如CurvedAnimation。您将控制器和动画传递到AnimationWidget中,并告诉控制器启动动画。

  • 图形绘制:

Android可以用Canvas 绘制自己想要的形状;

iOS 中通过 CoreGraphics 来在屏幕上绘制线条和形状;

Flutter则是通过两个类实现这种绘制画布的,CustomPaint和CustomPainter,它们实现您的算法以绘制到画布。

void paint(Canvas canvas, Size size) {

    var paint = new Paint()

      ..color = Colors.black

      ..strokeCap = StrokeCap.round

      ..strokeWidth = 5.0;

    for (int i = 0; i < points.length - 1; i++) {

      if (points[i] != null && points[+ 1] != null)

        canvas.drawLine(points[i], points[+ 1], paint);

}

  • 构建自定义Widgets:

在Android中继承View或已经存在的某个控件,然后覆盖其绘制方法来实现自定义View。

iOS中UIView 的子类,或使用已经存在的 view 来重载并实现方法,以达到特定的功能;

Flutter通常是通过组合其它widget来实现的,而不是继承。例如:构建持有一个label的CustomButton。这是通过将Text与RaisedButton组合来实现的,而不是扩展RaisedButton并重写其绘制方法实现

class CustomButton extends StatelessWidget {

  final String label;

  CustomButton(this.label);

  @override

  Widget build(BuildContext context) {

    return new RaisedButton(onPressed: () {}, child: new Text(label));

  }}

  • 异步UI:

Dart是单线程执行模型,支持Isolates(在另一个线程上运行Dart代码的方式)、事件循环和异步编程。 除非您启动一个Isolate,否则您的Dart代码将在主UI线程中运行,并由事件循环驱动(译者语:和JavaScript一样)。

  • AsyncTask和IntentService:

在Android中,当你想访问一个网络资源时,你通常会创建一个AsyncTask,它将会在主线程之外防止UI线程阻塞,AsyncTask有一个线程池,可以为你管理线程;

Flutter是单线程的,运行一个事件循环(如Node.js),所以您不必担心线程管理或者使用AsyncTasks、IntentServices。要异步运行代码,可以将函数声明为异步函数,并在该函数中等待这个耗时任务

loadData() async {

String dataURL = "https://jsonplaceholder.typicode.com/posts";

  http.Response response = await http.get(dataURL);

  setState(() {

    widgets = JSON.decode(response.body);

  });}

这种情况android上用AsyncTask会覆盖三个方法OnPreExecute、doInBackground和onPostExecute,而flutter只需等待(await)一个长时间运行的函数,而Dart的事件循环将负责其余的事情。这种情况只适用于数据量娇小的轻小的情况,当数据量较大的时UI线程可能会挂起;此时flutter可以利用多个CPU内核来执行耗时或计算密集型任务。这是通过使用Isolates来完成的。

loadData() async {

   ReceivePort receivePort = new ReceivePort();

    await Isolate.spawn(dataLoader, receivePort.sendPort);

    // The 'echo' isolate sends it's SendPort as the first message

    SendPort sendPort = await receivePort.first;

    List msg = await sendReceive(sendPort, "https://jsonplaceholder.typicode.com/posts");

    setState(() {

      widgets = msg;

    });

  }

  • 网络请求

Android用的时OkHttp而Flutter用的是“http” package,它 、抽象出了许多常用的API,可以简单有效的发起网络请求

  • 第三方框架的引入

Android可以直接下载拖入,Gradle文件来添加依赖项;

flutter只需要在pubspec.yaml文件夹中的dependencies下加入对应的sdk名以及对应版本后在终端上输入packege get即可导入

监听生命周期:Android可以覆盖Activity的方法来捕获Activity的生命周期回调;flutter中可以通过挂接到WidgetsBinding观察并监听didChangeAppLifecycleState更改事件来监听生命周期事件

@override

  void initState() {

super.initState();

    WidgetsBinding.instance.addObserver(this);

  }

  @override

  void dispose() {

    WidgetsBinding.instance.removeObserver(this);

    super.dispose();

  }

  @override

  void didChangeAppLifecycleState(AppLifecycleState state) {

    setState(() {

      _lastLifecyleState = state;

    });

  }

  • 布局方式:

Android中Linearlayout线性布局可以用flutter中的Row和Column来替代实现;

 

@override

Widget build(BuildContext context) {

  return new Row(或者Column)(

    mainAxisAlignment: MainAxisAlignment.center,

    children: <Widget>[

      new Text('One'),

      new Text('Two'),

      new Text('Three'),

      new Text('Four'),

    ],

Android中的RelativeLayout相对布局,在flutter中可以通过使用Column、Row和Stack的组合来实现RelativeLayout的效果;

Android中的ScrollView和ListView都可以用flutter的ListView来实现其效果;

ListView(

    children: <Widget>[

      new Text('Row One'),

      new Text('Row Two'),

      new Text('Row Three'),

      new Text('Row Four'),

    ],

  );

  • onClick方法:

Android中通过调用方法setOnClickListener将OnClick绑定到按钮等view上;

 iOS 中,给一个 view 添加 GestureRecognizer 来处理点击事件;

Flutter中1.对于本身支持点击的Widget如:Raisedbutton,floatButton等都有onPressed方法;2.对于包含点击事件的Widget可以将其包装到GestureDetector中,并将处理函数传递给onTap参数;

GestureDetector(

        child: new FlutterLogo(

          size: 200.0,

        ),

        onTap: () {

          print("tap");

        },

      ),

注:widget手势:Tap:onTapDown,onTapUp,onTap,onTapCancel

Double tap:onDoubleTap 用户快速连续两次在同一位置轻敲屏幕.

长按:onLongPress

垂直拖动:onVerticalDragStart,onVerticalDragUpdate,onVerticalDragEnd

水平拖拽:onHorizontalDragStart,onHorizontalDragUpdate,onHorizontalDragEnd

Flutter使用GPS权限.https://pub.dartlang.org/packages/location

在Android studio或Xcode的对应项目中开启权限,

用法:

import 'package:location/location.dart';

var currentLocation = LocationData;

var location = new Location();

// Platform messages may fail, so we use a try/catch PlatformException.try {

  currentLocation = await location.getLocation();

} on PlatformException catch (e) {

  if (e.code == 'PERMISSION_DENIED') {

    error = 'Permission denied';

  } 

  currentLocation = null;

}

var location = new Location();

location.onLocationChanged().listen((LocationData currentLocation) {

  print(currentLocation.latitude);

  print(currentLocation.longitude);

});

 

flutter使用相机权限.https://pub.dartlang.org/packages/image_picker

在Android studio或Xcode的对应项目中开启权限,

用法:

import 'package:image_picker/image_picker.dart';

class MyHomePage extends StatefulWidget {

  @override

  _MyHomePageState createState() => _MyHomePageState();

}

class _MyHomePageState extends State<MyHomePage{

  File _image;

 Future getImage() async {

    var image = await ImagePicker.pickImage(source: ImageSource.camera);

   setState(() {

      _image = image;

    });

  }

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐