Flutter学习教程flutter 专题 移动 前端 Python Android Java

Flutter

2018-03-29  本文已影响4882人  coofee

[TOC]

0x00 Flutter

flutter是google开发的移动端UI框架,支持android和ios。该框架使用dart语言进行开发,在skia的基础上开发了一套公共组件达到android与ios共用代码的目的。

1. Flutter系统架构

flutter_arch.png

2. Platform Channels

flutter使用methodChannel/flutterMethodChannel来访问系统原生api。


platform_channels.png

0x01 使用Flutter开发应用程序

1. 下载配置Flutter SDK

export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
$ git clone -b beta https://github.com/flutter/flutter.git
$ export PATH=`pwd`/flutter/bin:$PATH
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v0.1.5, on Mac OS X 10.11.6 15G19009, locale zh-Hans)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[!] iOS toolchain - develop for iOS devices (Xcode 7.2.1)
    ✗ Flutter requires a minimum Xcode version of 9.0.0.
      Download the latest version or update via the Mac App Store.
    ✗ ios-deploy not installed. To install:
        brew install ios-deploy
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without resolving iOS dependencies with CocoaPods, plugins will not work on iOS.
        For more info, see https://flutter.io/platform-plugins
      To install:
        brew install cocoapods
        pod setup
[✓] Android Studio (version 3.0)
[✓] Android Studio (version 2.3)
[!] IntelliJ IDEA Community Edition (version 2017.2.6)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
[!] VS Code (version 1.21.0)
[!] Connected devices
    ! No devices available

! Doctor found issues in 4 categories.

2. 使用Android Studio开发Demo

1. 创建应用

create_flutter_app_1.png create_flutter_app_2.png create_flutter_app_3.png create_flutter_app_4.png

2. 项目结构

使用android studio创建出来的项目目录结构大致如下:

app_struct.png

3. 调试与运行

4. 热加载

flutter中热加载的概念和android开发中的Instant run类似,同样也是点击⚡️按钮启用热加载功能。但是其拥有以下优点:

  1. 点击保存按钮或者保存快捷键,也会触发热加载功能(⚡️按钮功能相同)。
  2. 热加载会保留先前的状态
  3. 快!快!快! 代码增量编译在秒级别,单行代码改变反应到应用程序UI改变耗时约1.5秒左右。

所以大家就可以像写web页面一样,可以边写->边保存->边查看效果,开发效率大大加快有没有,再也不用等等等有没有。。。

热加载前 代码变动 热加载后
可以看到应用程序的计数器的值是2. app_hot_reload_before.png 修改字符显示,添加“吼吼吼吼”到文本中,然后保存触发热加载。 app_hot_reload_with_state.png 可以看到文本字符发生改变,但是计数器的值未发生变化,仍然是2. app_hot_reload_after.png

5. 应用程序结构与兼容性

1. 应用程序结构

首先我们打开项目根目录中的build文件夹,该文件包含了编译app的全部生成文件,其结构与android应用程序一致(注意:build目录在android studio中不显示,可以通过terminal打开或查看)。

apk_location.png

接下来,我们可以通过android studio直接打开该apk,可以发现仅仅只有一个页面的flutter应用大小已经达到了25MB左右,分析其结构(见下图),其包含了全部abi类型的so文件,导致apk整体比较大,排除掉x86x86_64平台的so文件之后,apk整体大小约11MB左右。

apk_struct_with_dart-1.png

使用release模式时,apk大小约8.1MB,大小比较正常。

apk_struct_mode_release.png

2. 应用程序兼容性

3. 开发Toast模块

这里我们直接使用android studio进行开发,如果大家需要直接使用flutter进行创建的话,可以直接参考platform-channels进行开发。

1. 使用dart编写公共的toast模块

import 'package:flutter/services.dart';

// 下划线开头的变量只在当前package中可见。
const _toast = const MethodChannel('com.coofee.flutterdemoapp/sdk/toast');

const int _LENGTH_SHORT = 0;

const int _LENGTH_LONG = 1;

void show(String text, int duration) async {
  try {
    await _toast.invokeMethod("show", {'text': text, 'duration': duration});
  } on Exception catch (e) {
    print(e);
  } on Error catch (e) {
    print(e);
  }
}

void showShort(String text) {
  show(text, _LENGTH_SHORT);
}

void showLong(String text) {
  show(text, _LENGTH_LONG);
}

2. 编写android端的代码并注册

package com.coofee.flutterdemoapp;

import android.os.Bundle;
import android.widget.Toast;

import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);

        new MethodChannel(getFlutterView(), "com.coofee.flutterdemoapp/sdk/toast")
                .setMethodCallHandler(new MethodChannel.MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                        if ("show".equals(methodCall.method)) {
                            String text = methodCall.argument("text");
                            int duration = methodCall.argument("duration");
                            Toast.makeText(MainActivity.this, text, duration).show();
                        }
                    }
                });
    }
}

3. 编写ios端代码并注册

ios端的代码与android端类似,但是需要使用FlutterMethodChannel进行处理,其他操作与android端一致,打开AppDelegate.m文件,添加如下代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];

  FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;

  FlutterMethodChannel* toastChannel = [FlutterMethodChannel
                                            methodChannelWithName:@"com.coofee.flutterdemoapp/sdk/toast"
                                            binaryMessenger:controller];

  [toastChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
      if ([@"show" isEqualToString:call.method]) {
          // 展示toast;
          NSLog(@"显示toast....")
      }
  }];

  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

4. 在flutter中调用toast模块

import 'sdk/toast.dart';

void _incrementCounter() {
  showShort('你点击了$_counter次');

  setState(() {
    // This call to setState tells the Flutter framework that something has
    // changed in this State, which causes it to rerun the build method below
    // so that the display can reflect the updated values. If we changed
    // _counter without calling setState(), then the build method would not be
    // called again, and so nothing would appear to happen.
    _counter++;
  });
}

5. 效果

toast_show.png

0x02 使用Dart 2

1. 升级flutter sdk

使用dart 2时,必须保证,Flutter SDK版本必须大于等于以下版本:

在Terminal中执行flutter --version命令,查看flutter的版本:

→ flutter --version
Flutter 0.1.5 • channel beta • https://github.com/flutter/flutter.git
Framework • revision 3ea4d06340 (3 weeks ago) • 2018-02-22 11:12:39 -0800
Engine • revision ead227f118
Tools • Dart 2.0.0-dev.28.0.flutter-0b4f01f759

在Terminal中执行flutter upgrade可以升级flutter。

2. 在android studio中启用dart 2

在android studio中启用dart2后,需要重启android studio使其生效。

dart-2.png

3. dart 1 vs dart 2

从下图可以看出dart2相对于dart1来说,省略了关键字new,使得声明式布局的可读性更进一步。

dart1_vs_dart2.png

4. dart2对apk大小的影响

从下图可以看出来,使用dart2时生成的apk比dart1打5MB左右(slow mode模式)。

apk_dart1_vs_dart2.png

0x03 Flutter's modes

从下图我们可以看到,flutter mode显示在在app的右上角。

mode_slow.png

flutter的应用程序有以下4中模式,分别使用不同的命令生成,且不同模式下生成的应用大小不一(如:release模式会去掉x86相关的so文件)

mode 命令
debug flutter run debug模式下的产物,且应用的右上角会显示slow mode字样,支持debug。
release flutter run --release UI上面不显示模式;禁止debug,且删除了debug相关的信息;关闭全部的断言检测,减小包大小,使其达到最佳性能。
profile flutter run --profile 调试性能,不支持模拟器。
test flutter test 和debug模式类似,不支持headless和桌面平台。

0x04 参考引用

上一篇下一篇

猜你喜欢

热点阅读