likes
comments
collection
share

Flutter 之 Widget 部件体验

作者站长头像
站长
· 阅读数 0

Flutter 与 React Native 的对比

React Native

React Native 是在原生 UI 的基础上进行了包装,把原生的 UIKit 框架中的 UI 控件包装成 React Native 中的控件,然后调用 React Native 也就是调用 js 代码,然后通过 js 代码调用 React Native 框架,然后通过 React Native 再调用原生的 UI 并进行加载。这样的话相对于 flutterReact Native 的渲染速度会慢了很多,但是 React Native 也做了很多的优化。最主要的弊端是它是基于原生 UI 进行包装的,如果原生 UI 更新了,React Native 也要进行更新,进行兼容,这样的话对原生的依赖就会非常大。还有就是因为 React Native 是通过 js 分别调用 iOS 跟安卓的原生 UI 进行渲染,所以虽然是一套代码,但是没法保证 UI 的展示效果一致。Weex 也会有类似问题。

Flutter

Flutter 能同时运行在 iOS 跟安卓上的原因是因为它们都安装了渲染引擎。Flutter 不是基于原生 UI 进行展示的,而是把渲染引擎安装到手机上,这里有个弊端就是每个基于 Flutter 开发的 App 都需要安装一个渲染引擎,就会导致 App 包会比较大。渲染引擎负责解析 dart 代码,然后展示渲染的界面。但是它的优点是效率高,而且不依赖原生 UI。而且都是依赖渲染引擎渲染,所以可以做到多端的 UI 高度统一。

React Native 具有热更新功能,相对这点来说 Flutter 就会比较麻烦,Flutter 具有热重载功能,但是只是限于 debug 版本下。relase 版本下开发者可以自定义开发。这里就需要涉及到渲染引擎,可以通过这种方式实现自己的热重载,实现了热重载也就实现了热更新,但是实现起来会比较复杂。谷歌之所以没有定义一套统一的标准供所有的开发者进行使用是因为苹果对这一块是禁止的,所以在苹果的生态下这种技术没有生存的空间,可能这也是谷歌没有这样去做的原因。

我们实现的 dart 代码通过渲染引擎的底层去解析,解析完成之后进行界面展示。但是渲染引擎在 iOS 跟安卓系统下执行的时候需要依赖各自的开发语言,iOS 下可以选择 swit 或者 oc,安卓下可以选择 java 或者 kotlin。同时 flutter 还能支持 macOSwindowslinuxweb。支持桌面系统的话需要到官网下载不同的 sdk 版本。

Flutter 小部件之 Text

void main() {
  // 对于不变的控件建议用 const 修饰
  runApp(const Center(
    child: Text(
      'hello flutter',
      // textDirection 代表文字的阅读方向
      textDirection: TextDirection.ltr,
    ),
  ));
}

Flutter 中如果要显示一个控件,需要在 main 函数中执行 runApp 方法,并在此方法中添加要显示的控件,这里 Center 也是一个 Widget,添加到 Center 中的子部件会居中显示。这里 Text 是一个文字显示部件,textDirection 代表文字的阅读方向。Flutter 中对于不会变的控件建议用 const 修饰,这样回提高渲染效率。因为 Flutter 是增量渲染,只会渲染改变的控件,用 const 修饰代表这个节点不会改变。

自定义 Widget

void main() => runApp(MyWidget());

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'hello flutter',
        // textDirection 代表文字的阅读方向
        textDirection: TextDirection.ltr,
      ),
    );
  }
}

Widget 分为有状态 StatefulWidget 与无状态 StatelessWidget 两种,无状态的 Widget 如果需要改变的话只能替换一个新的 Widget,而有状态的 Widget 可以修改里面的子部件。代码示例中我们自定义了一个继承与 无状态 StatelessWidgetWidget

Text 部件文字样式

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'hello flutter',
        // textDirection 代表文字的阅读方向
        textDirection: TextDirection.ltr,
        style: TextStyle(
          // 文字颜色
          color: Colors.red,
          // 文字大小
          fontSize: 40.0,
          // 粗体
          fontWeight: FontWeight.bold
        ),
      ),
    );
  }
}

Flutter 之 Widget 部件体验

这里我们设置了文字的大小,颜色跟样式,更多的属性设置大家也可以点进入看或者看下官方文档。

MaterialApp

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
     body: MyWidget(),
      ),
    );
  }
}

Flutter 之 Widget 部件体验

ListView

class Car {
  const Car({this.name, this.imageUrl});
  final String? name;
  final String? imageUrl;
}

final List<Car> datas = [
  const Car(
    name: '保时捷918 Spyder',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '兰博基尼Aventador',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '法拉利Enzo',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: 'Zenvo ST1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '迈凯伦F1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '萨林S7',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '科尼赛克CCR',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-01ced8f6f95219ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '布加迪Chiron',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7fc8359eb61adac0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '轩尼诗Venom GT',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-d332bf510d61bbc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  const Car(
    name: '西贝尔Tuatara',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-3dd9a70b25ae6bc9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  )
];
import 'package:demo/Model/car_model.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {

  Widget _itemForRow(BuildContext context, int index) {
    return Container(
      color: Colors.white,
      margin: EdgeInsets.all(10),
      child: Column(
        children: [
          Image.network(datas[index].imageUrl ?? ''),
          SizedBox(height: 10),
          Text(datas[index].name ?? '')
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      appBar: AppBar(
        title: const Text('list Demo'),
      ),
      body: ListView.builder(
        itemBuilder: _itemForRow,
        itemCount: datas.length,
      ),
    );
  }
}

Flutter 之 Widget 部件体验

这里我们用 ListView 部件实现一个列表,创建 ListView 的时候需要实现两个属性 itemBuilderitemCountitemBuilderIndexedWidgetBuilder 类型,typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index)。我们定义了一个私有方法 _itemForRow 返回列表中的每一个视图,相当于 UITableView 中的 tableView:cellForRowAtIndexPath: 方法,返回一个 cellitemCount 代表列表中数据的条数。