Flutter 3.0首次运行时卡在"Running Gradle task assembleDebug"的解决办法

第一步

找到flutter sdk路径下的这个文件

flutter/packages/flutter_tools/gradle/flutter.gradle

打开,并找到这个位置

1
2
3
4
5
6
7
buildscript {
repositories {
google()
mavenCentral()
}
...
}

注释掉 google()mavenCentral() ,并更改为

1
2
3
4
5
6
7
8
9
10
buildscript {
repositories {
// google()
// mavenCentral()
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
}
...
}

第二步

找到当前工程路径下的这个文件

/android/build.gradle

和第一步一样,打开,并注释掉 google()mavenCentral()并更改

注意第二步有两处,所以要改两个地方

第三步

还是这个文件

/android/build.gradle

找到DEFAULT_MAVEN_HOST并替换为国内的镜像地址

1
2
3
4
5
class FlutterPlugin implements Plugin<Project> {
// private static final String DEFAULT_MAVEN_HOST = "https://storage.googleapis.com";
private static final String DEFAULT_MAVEN_HOST = "https://storage.flutter-io.cn";
...
}

基本上完成上面这三步,就可以运行如下命令尝试再次启动了

1
flutter clean
1
flutter run

什么?你还不行啊。。。我倒,接着往下看吧,真没想到你这么倒霉

第四步

有可能是第三步的镜像地址挂了,可以把第三步再改回来,咱们改host

打开这个网站 https://tool.chinaz.com/speedtest/storage.googleapis.com

获取你的能访问到的加速ip地址,改hosts

有好多个呢,你自己试试吧

1
2
3
4
5
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost

142.251.43.16 storage.googleapis.com # 例如这样改,Mac和Linux不做介绍

再试试咯,不行就往下走

1
flutter clean
1
flutter run

第五步

到这基本上宣告你的gradle是死活下载不下来了,只能离线下载了,找到工程目录下的这个文件打开,找到里面的distributionUrl

/android/gradle/wrapper/gradle-wrapper.properties

1
2
...
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

你看啊,我这里是gradle-7.5-all.zip

那就去访问gradle的离线下载网站吧,找到gradle-7.5-all.zip并且下载下来

https://services.gradle.org/distributions/

然后去系统的gradle存放目录替换掉死活下载不下来的那些东西

例如我是C:\Users\vear\.gradle\wrapper\dists\gradle-7.5-all\6qsw290k5lz422uaf8jf6m7co\gradle-7.5-all.zip

那就把C:\Users\vear\.gradle\wrapper\dists\gradle-7.5-all\6qsw290k5lz422uaf8jf6m7co下面的东西全删了

把新下载的gradle-7.5-all.zip拷贝进去

再回来试试咯,反正我是行了,你不行就只能另请高明了

1
flutter clean
1
flutter run

flutter神器getx介绍

基于官网文档提炼关键部分,方便安装使用

详细文档getx官方中文文档

关于Get

GetX 是 Flutter 上的一状态管理、依赖注入和路由管理的包

安装

将 Get 添加到你的 pubspec.yaml 文件中。

1
2
dependencies:
get:

在需要用到的文件中导入

1
import 'package:get/get.dart';

GetX的计数器示例

Flutter默认创建的 “计数器 “项目有100多行(含注释),为了展示Get的强大功能,我将使用 GetX 重写一个”计数器 Plus版”,实现:

  • 每次点击都能改变状态
  • 在不同页面之间切换
  • 在不同页面之间共享状态
  • 将业务逻辑与界面分离

而完成这一切只需 26 行代码(含注释)

  • 第一步:
    在你的MaterialApp前添加 “Get”,将其变成GetMaterialApp,GetMaterialApp会创建注入路由
1
void main() => runApp(GetMaterialApp(home: Home()));
  • 第二步:
    创建你的业务逻辑类,并将所有的变量,方法和控制器放在里面。
    你可以使用一个简单的”.obs “使任何变量成为可观察的。
1
2
3
4
class Controller extends GetxController{
var count = 0.obs;
increment() => count++;
}
  • 第三步:
    创建你的界面,使用StatelessWidget节省一些内存,使用Get不再需要使用StatefulWidget。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Home extends StatelessWidget {

@override
Widget build(context) {

// 使用Get.put()实例化你的类,使其对当下的所有子路由可用。
final Controller c = Get.put(Controller());

return Scaffold(
// 使用Obx(()=>每当改变计数时,就更新Text()。
appBar: AppBar(title: Obx(() => Text("Clicks: ${c.count}"))),

// 用一个简单的Get.to()即可代替Navigator.push那8行,无需上下文!
body: Center(child: ElevatedButton(
child: Text("Go to Other"), onPressed: () => Get.to(Other()))),
floatingActionButton:
FloatingActionButton(child: Icon(Icons.add), onPressed: c.increment));
}
}

class Other extends StatelessWidget {
// 你可以让Get找到一个正在被其他页面使用的Controller,并将它返回给你。
final Controller c = Get.find();

@override
Widget build(context){
// 访问更新后的计数变量
return Scaffold(body: Center(child: Text("${c.count}")));
}
}

三大功能

响应式状态管理器

要想让它变得可观察,你只需要在它的末尾加上”.obs”。

1
var name = 'Jonatas Borges'.obs;

而在UI中,当你想显示该值并在值变化时更新页面,只需这样做。

1
Obx(() => Text("${controller.name}"));

这就是全部,就这么简单。

路由管理

在你的MaterialApp前加上 “Get”,把它变成GetMaterialApp。

1
2
3
GetMaterialApp( // Before: MaterialApp(
home: MyHome(),
)

导航到新页面

1
2

Get.to(NextScreen());
1
2

Get.toNamed('/details');

要关闭snackbars, dialogs, bottomsheets或任何你通常会用Navigator.pop(context)关闭的东西。

1
Get.back();

进入下一个页面,但没有返回上一个页面的选项(用于闪屏页,登录页面等)。

1
Get.off(NextScreen());

进入下一个页面并取消之前的所有路由(在购物车、投票和测试中很有用)。

1
Get.offAll(NextScreen());

依赖管理

Get依赖管理器就是导入状态管理

注入依赖:

1
Get.put<PutController>(PutController());

获取依赖:

1
2
3
4
5
6
Controller putController = Get.find<PutController>();
```

直接使用
```dart
Text(putController.textFromApi);

提示: Get依赖管理与包的其他部分是解耦的,所以可以导入多个

例子

Get.find() ,它可以帮你找到控制器,这个东西也是有限制的,这东西就找不到直接实例化的控制器,只能找到通过依赖注入的控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class ListPage extends StatelessWidget {
// 直接实例化,Get.find找不到
final ListController controller = ListController();

final GoodsController goodsController = Get.put(GoodsController());

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("依赖管理"),
centerTitle: true,
),
body: Column(
children: [
Text("渲染ListController的数据"),
Row(
children: controller.lists.map((item) => Text("$item, ")).toList(),
),
SizedBox(height: 50),
Text("渲染GoodsController的数据"),
Row(
children:
goodsController.goods.map((item) => Text("$item, ")).toList(),
),
SizedBox(height: 50),
Text("通过Get.find查找GoodsController"),
Row(
children: Get.find<GoodsController>()
.goods
.map((item) => Text("$item, "))
.toList(),
),
// 以下报错 【ListController not found, you need to call Get.put() 】
SizedBox(height: 50),
Text("通过Get.find查找ListController"),
Row(
children: Get.find<ListController>()
.lists
.map((item) => Text("$item, "))
.toList(),
)
],
),
);
}
}