likes
comments
collection
share

Flutter版本从1.7.8到3.7.9的升级之旅

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

1、前言

个人于2019年5月开源了WanAndroid的Flutter版本,截止目前也有660+的star,在过去的4年中,大家对Flutter的关注也越来越多,且有很多已经在商业项目中使用。

这中间也陆陆续续有不少朋友问我什么时候能升级一下Flutter的版本,毕竟太老了。所以这次也是借着这个机会,把这个项目升级一下,熬了两个大夜,终于算是适配好了。

项目地址: https://github.com/yechaoa/wanandroid_flutter

1.1、升级适配一览

Flutter版本从1.7.8到3.7.9的升级之旅

1.2、效果演示

Flutter版本从1.7.8到3.7.9的升级之旅

3、环境

3.1、升级前

  • Flutter:1.7.8+hotfix.3
  • Dart:2.4.0
  • Date:2019-07-09 13:14:38
➜  wanandroid_flutter git:(master) ✗ flutter --version
  ╔════════════════════════════════════════════════════════════════════════════╗
  ║ A new version of Flutter is available!                                     ║
  ║                                                                            ║
  ║ To update to the latest version, run "flutter upgrade".                    ║
  ╚════════════════════════════════════════════════════════════════════════════╝


Flutter 1.7.8+hotfix.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b712a172f9 (39 个月前) • 2019-07-09 13:14:38 -0700
Engine • revision 54ad777fd2
Tools • Dart 2.4.0

3.2、升级后

  • Flutter:3.7.9
  • Dart:2.19.6
  • Date:2023-03-30 10:59:36
➜  wanandroid_flutter git:(master) ✗ flutter --version
Flutter 3.7.9 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 62bd79521d (3 天前) • 2023-03-30 10:59:36 -0700
Engine • revision ec975089ac
Tools • Dart 2.19.6 • DevTools 2.20.1

4、环境配置

由于时间久远,中间换了电脑,终端插件也换了,之前的一些配置失效了,所以先配置环境。

第一步,环境配好之后先执行flutter doctor

4.1、无法打开“dart”,因为无法验证开发者

提示我:无法打开“dart”,因为无法验证开发者。

Flutter版本从1.7.8到3.7.9的升级之旅

因为mac系统增强了安全性的设置,所以需要在隐私与安全性里设置一下允许权限。

Flutter版本从1.7.8到3.7.9的升级之旅

4.2、无法打开“kernal-service.dart.snapshot”,因为无法验证开发者。

然后继续,又提示:无法打开“kernal-service.dart.snapshot”,因为无法验证开发者。

Flutter版本从1.7.8到3.7.9的升级之旅

按照上面刚才的操作,继续“允许”就行了。

4.3、最新版本

环境配置搞完了之后,Flutter终于算是可以用了。

执行flutter --version看看现在的版本是多少

➜  wanandroid_flutter git:(master) ✗ flutter --version
  ╔════════════════════════════════════════════════════════════════════════════╗
  ║ A new version of Flutter is available!                                     ║
  ║                                                                            ║
  ║ To update to the latest version, run "flutter upgrade".                    ║
  ╚════════════════════════════════════════════════════════════════════════════╝


Flutter 1.7.8+hotfix.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b712a172f9 (39 个月前) • 2019-07-09 13:14:38 -0700
Engine • revision 54ad777fd2
Tools • Dart 2.4.0

顺便看看最新的版本是多少

最新正式版:docs.flutter.dev/development…

Flutter版本从1.7.8到3.7.9的升级之旅

4.4、doctor检测

Flutter环境虽然搞好了,但是项目还不能运行起来,dart文件都不能识别

Flutter版本从1.7.8到3.7.9的升级之旅

先不管,先执行flutter upgrade试试看。

然后...不出意外的就执行挂了

Oops; flutter has exited unexpectedly.
Sending crash report to Google.
Crash report written to /Users/yechao/FlutterProjects/wanandroid_flutter/flutter_01.log;
please let us know at https://github.com/flutter/flutter/issues.

log:

## command

flutter upgrade

## exception

VersionCheckError: VersionCheckError: Command exited with code -9: git log -n 1 --pretty=format:%ad --date=iso
Standard error: 

```
#0      _runSync (package:flutter_tools/src/version.dart:522:5)
#1      FlutterVersion._latestGitCommitDate (package:flutter_tools/src/version.dart:142:12)
#2      FlutterVersion.frameworkCommitDate (package:flutter_tools/src/version.dart:133:37)
#3      FlutterVersion.toString (package:flutter_tools/src/version.dart:110:99)
#4      UpgradeCommandRunner.updatePackages (package:flutter_tools/src/commands/upgrade.dart:190:32)
<asynchronous suspension>
#5      UpgradeCommandRunner.runCommand (package:flutter_tools/src/commands/upgrade.dart:90:11)
<asynchronous suspension>
#6      UpgradeCommand.runCommand (package:flutter_tools/src/commands/upgrade.dart:47:32)
<asynchronous suspension>

看起来是dart版本的问题。然后在github的issue上看到有同样的反馈,标记已解决,但是也没看到解决方案在哪里...

然后执行flutter doctor看看

➜  wanandroid_flutter git:(master) ✗ flutter doctor 
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.7.9, on macOS 13.2 22D49 darwin-arm64, locale zh-Hans-CN)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✗] Xcode - develop for iOS and macOS
    ✗ Xcode installation is incomplete; a full installation is necessary for iOS development.
      Download at: https://developer.apple.com/xcode/download/
      Or install Xcode via the App Store.
      Once installed, run:
        sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
        sudo xcodebuild -runFirstLaunch
    ✗ CocoaPods installed but not working.
        You appear to have CocoaPods installed but it is not working.
        This can happen if the version of Ruby that CocoaPods was installed with is different from the one being used to invoke it.
        This can usually be fixed by re-installing CocoaPods.
      To re-install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.3)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

! Doctor found issues in 2 categories.

有一堆报错,先解决了再说。

4.5、cmdline-tools component is missing

说是cmdline-tools没装,那就装吧

Flutter版本从1.7.8到3.7.9的升级之旅

4.6、Android license status unknown.

然后是Android license status unknown.

执行flutter doctor --android-licenses

➜  wanandroid_flutter git:(master) ✗ flutter doctor --android-licenses
[=======================================] 100% Computing updates...             
3 of 7 SDK package licenses not accepted.
Review licenses that have not been accepted (y/N)? y

1/3: License android-googletv-license:
---------------------------------------
Terms and Conditions

// ....
10.8 Open Source Software. In the event Open Source software is included with Evaluation Software, such Open Source software is licensed pursuant to the applicable Open Source software license agreement identified in the Open Source software comments in the applicable source code file(s) and/or file header as indicated in the Evaluation Software. Additional detail may be available (where applicable) in the accompanying on-line documentation. With respect to the Open Source software, nothing in this Agreement limits any rights under, or grants rights that supersede, the terms of any applicable Open Source software license agreement.
---------------------------------------
Accept? (y/N): y
All SDK package licenses accepted

多次同意之后就ok了。

再次执行flutter doctor

➜  wanandroid_flutter git:(master) ✗ flutter doctor                   
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.7.9, on macOS 13.2 22D49 darwin-arm64, locale zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[✗] Xcode - develop for iOS and macOS
    ✗ Xcode installation is incomplete; a full installation is necessary for iOS development.
      Download at: https://developer.apple.com/xcode/download/
      Or install Xcode via the App Store.
      Once installed, run:
        sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
        sudo xcodebuild -runFirstLaunch
    ✗ CocoaPods installed but not working.
        You appear to have CocoaPods installed but it is not working.
        This can happen if the version of Ruby that CocoaPods was installed with is different from the one being used to invoke it.
        This can usually be fixed by re-installing CocoaPods.
      To re-install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2022.2.3)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

! Doctor found issues in 1 category.

4.7、安装xcode

就只剩xcode的问题了,去装一下,换电脑之后还没装过。

安装完成,再次执行flutter doctor

[✗] Xcode - develop for iOS and macOS
    ✗ Xcode installation is incomplete; a full installation is necessary for iOS development.
      Download at: https://developer.apple.com/xcode/download/
      Or install Xcode via the App Store.
      Once installed, run:
        sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
        sudo xcodebuild -runFirstLaunch
    ✗ CocoaPods installed but not working.
        You appear to have CocoaPods installed but it is not working.
        This can happen if the version of Ruby that CocoaPods was installed with is different from the one being used to invoke it.
        This can usually be fixed by re-installing CocoaPods.
      To re-install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.

然后我们按照提示,执行一下

sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer

输入密码,然后执行

sudo xcodebuild -runFirstLaunch

搞完又提示我这个:

[!] Xcode - develop for iOS and macOS (Xcode 14.3)
    ✗ CocoaPods installed but not working.
        You appear to have CocoaPods installed but it is not working.
        This can happen if the version of Ruby that CocoaPods was installed with is different from the one being used to invoke it.
        This can usually be fixed by re-installing CocoaPods.
      To re-install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.

CocoaPods installed but not working.然后又提到了Ruby,看起来是版本不兼容导致的。

4.8、升级ruby

➜  ~ which ruby 
/usr/bin/ruby
➜  ~ ruby -v
ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin22]
➜  ~ brew install ruby
...

升级完执行:

sudo gem install cocoapods

重新装一下cocoapods

然后不出意外的也报错了

ERROR:  Error installing cocoapods:
        The last version of activesupport (>= 5.0, < 8) to support your Ruby & RubyGems was 6.1.7.3. Try installing it with `gem install activesupport -v 6.1.7.3` and then running the current command again
        activesupport requires Ruby version >= 2.7.0. The current ruby version is 2.6.10.210.

按照提示 执行:

gem install activesupport -v 6.1.7.3

如果提示没有权限就给一下系统权限:

sudo gem update --system

然后再次执行:

sudo gem install cocoapods

5、升级

5.1、执行flutter upgrade

安装完,再次执行flutter upgrade进行版本升级

➜  wanandroid_flutter git:(master) ✗ flutter upgrade
Flutter is already up to date on channel stable
Flutter 3.7.9 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 62bd79521d (20 小时前) • 2023-03-30 10:59:36 -0700
Engine • revision ec975089ac
Tools • Dart 2.19.6 • DevTools 2.20.1

ok,可以升级了。

5.2、升级插件

然后这时候我们还需要再把flutterdart的插件安装/升级一下

Flutter版本从1.7.8到3.7.9的升级之旅

然后重启,这时候我们的dart文件就可以识别了

Flutter版本从1.7.8到3.7.9的升级之旅

但是还有一堆报错,Flutter版本从1.7.8升级到3.7.9,跨度这么大,肯定是要适配的。

6、适配

先执行一下flutter pub get拉一下最新的依赖配置。

执行完,虽然报错少了一些,但是还有很多。

找问题最直接的方式就是,直接编译

6.1、Your Flutter application is created using an older version of the Android embedding.

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Warning
──────────────────────────────────────────────────────────────────────────────
Your Flutter application is created using an older version of the Android
embedding. It is being deprecated in favor of Android embedding v2. To migrate
your project, follow the steps at:

https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
The detected reason was:

  /Users/yechao/FlutterProjects/wanandroid_flutter/android/app/src/main/AndroidManifest.xml uses `android:name="io.flutter.app.FlutterApplication"`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Build failed due to use of deprecated Android v1 embedding.

提示有废弃的配置,并给了升级文档链接:github.com/flutter/flu…

按照文档提示修改AndroidManifest文件中的android:name属性:

Previous configuration:

<application
  android:name="io.flutter.app.FlutterApplication"
  >
  <!-- code omitted -->
</application>

New configuration:

<application
  android:name="${applicationName}"
  >
  <!-- code omitted -->
</application>

6.2、No <meta-data android:name="flutterEmbedding" android:value="2"/> in xxx

再次编译

The detected reason was:

  No `<meta-data android:name="flutterEmbedding" android:value="2"/>` in /Users/yechao/FlutterProjects/wanandroid_flutter/android/app/src/main/AndroidManifest.xml

没有meta-data配置,那就加:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.yechaoa.wanandroid_flutter">
    <application >
        
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />

    </application>
</manifest>

6.3、插件升级

再次编译

The plugins `flutter_webview_plugin, fluttertoast` use a deprecated version of the Android embedding.
To avoid unexpected runtime failures, or future build failures, try to see if these plugins support the Android V2 embedding. Otherwise, consider removing them since a future release of Flutter will remove these deprecated APIs.
If you are plugin author, take a look at the docs for migrating the plugin to the V2 embedding: https://flutter.dev/go/android-plugin-migration.
Launching lib/main.dart on sdk gphone64 arm64 in debug mode...
Running Gradle task 'assembleDebug'...

提示这俩插件flutter_webview_plugin, fluttertoast用了过时api,需要升级一下。

顺便把所有的插件都检查升级一下(还好当时都留了插件地址)。

6.4、flutter_webview_plugin

遗憾的是flutter_webview_plugin已经不维护了,

The plugin `flutter_webview_plugin` uses a deprecated version of the Android embedding.
To avoid unexpected runtime failures, or future build failures, try to see
if this plugin supports the Android V2 embedding. Otherwise, consider
removing it since a future release of Flutter will remove these deprecated APIs.
If you are plugin author, take a look at the docs for migrating the plugin
to the V2 embedding: https://flutter.dev/go/android-plugin-migration.

但是在github找到了解决办法:github.com/fluttercomm…

dependencies:
	flutter_webview_plugin:
    git: https://github.com/nuc134r/flutter_webview_plugin.git

最后都升级了这些:

Flutter版本从1.7.8到3.7.9的升级之旅

升级完执行flutter pub get 重新拉一下。

此时项目还是不能运行的,因为文件里还是有一些报错,这时候就需要手动去改适配了。

6.5、BottomNavigationBarItem

Flutter版本从1.7.8到3.7.9的升级之旅

源码:

The argument [icon] should not be null and the argument [label] 
should not be null when used in a Material Design's [BottomNavigationBar].

原来是改了字段,titlelabel

改前:

BottomNavigationBarItem(
  icon: Icon(Icons.apps),
  title: Text(YStrings.project),
),

改后:

BottomNavigationBarItem(
  icon: Icon(Icons.apps),
  label: YStrings.project,
),

6.6、Fluttertoast

Flutter版本从1.7.8到3.7.9的升级之旅

源码:

Flutter版本从1.7.8到3.7.9的升级之旅

原来是timeInSecForIos字段改成 timeInSecForIosWeb了,源码默认值就是1,可以直接去掉这个属性。

6.7、FlatButton

Flutter版本从1.7.8到3.7.9的升级之旅

找不到FlatButton,我在官网 Material Components widgets中确实没找到,暂时用TextButton代替吧,就换个名字,其他不用改。

6.8、RaisedButton

Flutter版本从1.7.8到3.7.9的升级之旅

同上,改用ElevatedButton代替吧。

6.9、Form

Flutter版本从1.7.8到3.7.9的升级之旅

源码:

  const Form({
    super.key,
    required this.child,
    this.onWillPop,
    this.onChanged,
    AutovalidateMode? autovalidateMode,
  }) : assert(child != null),
       autovalidateMode = autovalidateMode ?? AutovalidateMode.disabled;

源码已经没autovalidate这个字段了,改用AutovalidateMode

修改:

child: Form(
  autovalidateMode: AutovalidateMode.onUserInteraction,
  // ...
),

6.10、showSnackBar

Flutter版本从1.7.8到3.7.9的升级之旅

没这个api? 应该是姿势不对。

原来是Scaffold改为ScaffoldMessenger了。

修改:

ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("已移除")));

6.11、EasyRefresh

Flutter版本从1.7.8到3.7.9的升级之旅

依赖版本升级了,flutter_easyrefresh: ^2.0.0 升到 easy_refresh: ^3.3.1,想必有很多api、使用姿势什么的都要重新适配,就得重新看下文档了。

修改后如下:

      body: EasyRefresh(
        header: PhoenixHeader(),
        footer: PhoenixFooter(),
        onRefresh: () async {
          await Future.delayed(Duration(seconds: 1), () {
            setState(() {
              _page = 0;
            });
            getHttp();
          });
        },
        onLoad: () async {
          await Future.delayed(Duration(seconds: 1), () async {
            setState(() {
              _page++;
            });
            getMoreData();
          });
        },
        child: SliverList(
          delegate: SliverChildBuilderDelegate(
            (context, index) {
              return getItem(index);
            },
            childCount: articleDatas.length,
          ),
        ),
      ),

原先自定义的PhoenixHeader现在内置就有了,直接删除自定义widget改用内置的。

slivers改为child

6.12、Dio

API文档:github.com/cfug/dio/bl…

变更记录:github.com/cfug/dio/bl…

6.12.1、connectTimeout

Flutter版本从1.7.8到3.7.9的升级之旅

改用Duration表示,比以前更规范了。

修改:

      //连接服务器超时时间,单位是秒.
      connectTimeout: Duration(seconds: 10),
      //响应流上前后两次接受到数据的间隔,单位为秒。
      receiveTimeout: Duration(seconds: 5),

6.12.2、InterceptorsWrapper

回调方法缺少InterceptorHandler参数。

改之前:

//添加拦截器
dio.interceptors.add(InterceptorsWrapper(onRequest: (RequestOptions options) {
  print("请求之前");
  // Do something before request is sent
  return options; //continue
}, onResponse: (Response response) {
  print("响应之前");
  // Do something with response data
  return response; // continue
}, onError: (DioError e) {
  print("错误之前");
  // Do something with response error
  return e; //continue
}));

改之后:

//添加拦截器
dio.interceptors.add(InterceptorsWrapper(onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
  print("请求之前");
  // 如果你想完成请求并返回一些自定义数据,你可以使用 `handler.resolve(response)`。
  // 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。
  return handler.next(options); //continue
}, onResponse: (Response response, ResponseInterceptorHandler handler) {
  print("响应之前");
  // 如果你想终止请求并触发一个错误,你可以使用 `handler.reject(error)`。
  return handler.next(response); // continue
}, onError: (DioError e, ErrorInterceptorHandler handler) {
  print("错误之前");
  // 如果你想完成请求并返回一些自定义数据,你可以使用 `handler.resolve(response)`。
  return handler.next(e);
}));

6.12.3、DioErrorType

字段变更,大写变小写。

改之前:

  /*
   * error统一处理
   */
  void formatError(DioError e) {
    if (e.type == DioErrorType.CONNECT_TIMEOUT) {
      // It occurs when url is opened timeout.
      print("连接超时");
    } else if (e.type == DioErrorType.SEND_TIMEOUT) {
      // It occurs when url is sent timeout.
      print("请求超时");
    } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) {
      //It occurs when receiving timeout
      print("响应超时");
    } else if (e.type == DioErrorType.RESPONSE) {
      // When the server response, but with a incorrect status, such as 404, 503...
      print("出现异常");
    } else if (e.type == DioErrorType.CANCEL) {
      // When the request is cancelled, dio will throw a error with this type.
      print("请求取消");
    } else {
      //DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null.
      print("未知错误");
    }
  }

改之后:

  /*
   * error统一处理
   */
  void formatError(DioError e) {
    if (e.type == DioErrorType.connectionTimeout) {
      // It occurs when url is opened timeout.
      print("连接超时");
    } else if (e.type == DioErrorType.sendTimeout) {
      // It occurs when url is sent timeout.
      print("请求超时");
    } else if (e.type == DioErrorType.receiveTimeout) {
      //It occurs when receiving timeout
      print("响应超时");
    } else if (e.type == DioErrorType.badResponse) {
      // When the server response, but with a incorrect status, such as 404, 503...
      print("出现异常");
    } else if (e.type == DioErrorType.cancel) {
      // When the request is cancelled, dio will throw a error with this type.
      print("请求取消");
    } else {
      //DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null.
      print("未知错误");
    }
  }

6.13、Gradle版本升级

以上全部改完之后再编译

1: Task failed with an exception.
-----------
* Where:
Build file '/Users/yechao/.pub-cache/hosted/pub.flutter-io.cn/fluttertoast-8.2.1/android/build.gradle' line: 25

* What went wrong:
A problem occurred evaluating project ':fluttertoast'.
> Failed to apply plugin [id 'kotlin-android']
   > The current Gradle version 5.4.1 is not compatible with the Kotlin Gradle plugin. Please use Gradle 6.1.1 or newer, or the previous version of the Kotlin plugin.

The current Gradle version 5.4.1 is not compatible with the Kotlin Gradle plugin. Please use Gradle 6.1.1 or newer, or the previous version of the Kotlin plugin.

fluttertoast8.2.1中依赖了kotlin-android插件,需要升级Gradle版本5.4.1到6.1.1或者更新。

这里选择升级Gradle版本到6.1.1,AGP用4.0.2。

升级完Gradle再次编译,又又又报错

../../.pub-cache/hosted/pub.flutter-io.cn/provide-1.0.2/lib/provide.dart:570:28: Error: The method 'inheritFromWidgetOfExactType' isn't defined for the class 'BuildContext'.
 - 'BuildContext' is from 'package:flutter/src/widgets/framework.dart' ('../../FlutterSDK/flutter/packages/flutter/lib/src/widgets/framework.dart').
Try correcting the name to the name of an existing method, or defining a method named 'inheritFromWidgetOfExactType'.
    final widget = context.inheritFromWidgetOfExactType(_InheritedProviders);
                           ^^^^^^^^^^^^^^^^^
Target kernel_snapshot failed: Exception

FAILURE: Build failed with an exception.

* Where:
Script '/Users/yechao/FlutterSDK/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 1151

* What went wrong:
Execution failed for task ':app:compileFlutterBuildDebug'.
> Process 'command '/Users/yechao/FlutterSDK/flutter/bin/flutter'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 14m 59s
Exception: Gradle task assembleDebug failed with exit code 1

这里有一个provide的报错,provide用于状态管理,但是已经不维护了,所以不如直接换成providergithub.com/rrousselGit…

6.14、Provider迁移

配置:

  runApp(MultiProvider(
    providers: [
      //将theme,favorite加到providers中
      ChangeNotifierProvider(create: (ctx) => ThemeProvide()),
      ChangeNotifierProvider(create: (ctx) => FavoriteProvide())
    ],
    child: MyApp(themeIndex),
  ));

读:

final int themeValue = context.watch<ThemeProvide>().value;

写:

context.read<ThemeProvide>().setTheme(position);

示例 ThemeProvide:

import 'package:flutter/material.dart';

class ThemeProvide with ChangeNotifier {
  int _themeIndex;

  int get value => _themeIndex;

  ThemeProvide();

  void setTheme(int index) async {
    _themeIndex = index;
    notifyListeners();
  }
}

6.15、不兼容的类型: MainActivity无法转换为FlutterEngine

迁移完了再次编译下

/Users/yechao/FlutterProjects/wanandroid_flutter/android/app/src/main/java/com/yechaoa/wanandroid_flutter/MainActivity.java:11: 错误: 不兼容的类型: MainActivity无法转换为FlutterEngine
    GeneratedPluginRegistrant.registerWith(this);
                                           ^
注: /Users/yechao/FlutterProjects/wanandroid_flutter/android/app/src/main/java/com/yechaoa/wanandroid_flutter/MainActivity.java使用或覆盖了已过时的 API。
注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
注: 某些消息已经过简化; 请使用 -Xdiags:verbose 重新编译以获得完整输出
1 个错误

FAILURE: Build failed with an exception.

指向GeneratedPluginRegistrant.registerWith(this);不兼容,那就改

GeneratedPluginRegistrant.registerWith(new FlutterEngine(this));

网上找到这个方案,换成FlutterEngine(this),结果不行。

然后在官网迁移的文档找到答案。github.com/flutter/flu…

不需要registerWith注册,前提是加了

<meta-data
    android:name="flutterEmbedding"
    android:value="2" />

并且,把原有的

import io.flutter.app.FlutterActivity;

改为

import io.flutter.embedding.android.FlutterActivity;

6.16、EasyRefresh再适配

然后再次编译。终于跑起来了,但是首页挂了

Flutter版本从1.7.8到3.7.9的升级之旅

报错:

PhoenixFooter does not support horizontal scrolling.
'package:easy_refresh/src/styles/phoenix/footer/phoenix_footer.dart':
Failed assertion: line 45 pos 12: 'state.axis == Axis.vertical'

The relevant error-causing widget was: 
  EasyRefresh EasyRefresh:file:///Users/yechao/FlutterProjects/wanandroid_flutter/lib/pages/homePage.dart:68:13
When the exception was thrown, this was the stack: 
#2      PhoenixFooter.build (package:easy_refresh/src/styles/phoenix/footer/phoenix_footer.dart:45:12)
#3      IndicatorNotifier._build (package:easy_refresh/src/notifier/indicator_notifier.dart:834:23)
#4      _EasyRefreshState._buildFooterView.<anonymous closure> (package:easy_refresh/src/easy_refresh.dart:593:34)
#5      _ValueListenableBuilderState.build (package:flutter/src/widgets/value_listenable_builder.dart:186:26)
#6      StatefulElement.build (package:flutter/src/widgets/framework.dart:5080:27)
#7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4968:15)
#8      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5133:11)
#9      Element.rebuild (package:flutter/src/widgets/framework.dart:4690:5)
#10     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2743:19)
#11     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:863:21)
#12     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:381:5)
#13     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1289:15)
#14     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1218:9)
#15     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1076:5)
#16     _invoke (dart:ui/hooks.dart:145:13)
#17     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:338:5)
#18     _drawFrame (dart:ui/hooks.dart:112:31)
(elided 2 frames from class _AssertionError)

PhoenixFooter does not support horizontal scrolling.

这就没办法了,要么去掉PhoenixFooter,要么把banner放到下拉刷新的上面,类似支付宝之前在页面中间的下拉刷新...

改造完是这样的:

Flutter版本从1.7.8到3.7.9的升级之旅

6.17、Invalid value: Valid value range is empty: 0

还要一个Error

RangeError (index): Invalid value: Valid value range is empty: 0

When the exception was thrown, this was the stack: 
#0      List.[] (dart:core-patch/growable_array.dart:264:36)
#1      _HomePageState.getRow (package:wanandroid_flutter/pages/homePage.dart:188:57)
#2      _HomePageState.build.<anonymous closure> (package:wanandroid_flutter/pages/homePage.dart:117:24)
#3      SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:487:22)
#4      SliverMultiBoxAdaptorElement._build (package:flutter/src/widgets/sliver.dart:1422:28)
#5      SliverMultiBoxAdaptorElement.createChild.<anonymous closure> (package:flutter/src/widgets/sliver.dart:1436:55)
#6      BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2682:19)
#7      SliverMultiBoxAdaptorElement.createChild (package:flutter/src/widgets/sliver.dart:1428:12)

页面渲染的时候数据还没到,这时候按下标取值就取不到,就error了。

也比较好改,加个判断就行

  Widget getRow(int i, int length) {

    if (length==0) return null;

    return GestureDetector(
      	// ...
    );
  }

6.18、布局溢出

Flutter版本从1.7.8到3.7.9的升级之旅

我们BaguTree的标签label太长了😅

这个比较好解决,加约束constraints限制显示长度就行了

constraints: BoxConstraints(maxWidth: 150),
child: Text(articleDatas[i].superChapterName,
    style: TextStyle(color: Theme.of(context).primaryColor),
    overflow: TextOverflow.ellipsis,
    maxLines: 1)),

7、最后

以上就是Flutter从1.7.8升级到3.7.9的全过程了,除此之外,还有搜索、登录、主题适配等功能的修改及优化,就不继续展开了。

总的来说,升级过程不算很顺利,各种编译/运行报错,疯狂翻源码,在Stack Overflow和GitHub的issue里面也是各种找解决方案,但是这个过程也可以看到Flutter的生态建设越来越成熟,有越来越多的人正在拥抱Flutter。

期待Flutter未来有更好的发展~

8、GitHub

https://github.com/yechaoa/wanandroid_flutter

9、相关文档

本文正在参加「金石计划」