【Android-Flutter】My Flutter development journey

Zero, documentation:

Foreign official website ( ❌科学上网): https://flutter.dev/
Foreign documents: https://docs.flutter.dev/

Domestic official website: https://flutter.cn
Domestic documents: https://flutter.cn/docs/

Other Chinese version documents ( 更适合新手): https://doc.flutterchina.club


1. Set up a Flutter development environment on Windows

❌It means that it may not be accessible in China, and other means such as scientific Internet access may be needed.

(1) Use Chinese mirror (❌See official documentation for details)

  • 将如下环境变量加入到【用户环境变量】中:
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
  • 在Windows中操作示例:
    Insert image description here

(2) Download the latest version of Flutter SDK (already includes Dart)

  • Go to 上面提供的官网download, such as ❌https://docs.flutter.dev/release/archive?tab=windows#windows - if you can’t access it from abroad, just take a look at the domestic one, or go online scientifically.

  • After the download is completed, unzip it to the C drive and create a new directory for management ( 不要放在高权限的路径for example, do not put it in C:\Program Files\).

  • This SDK is actually a command, so we need to configure environment variables for easy use: like other SDKs, under " " 用户变量: “Pathadd a flutter\binfull path as its value - Tip: the command name isflutter

(3) Run the first flutter command - flutter doctor(doctor check command)

提示:first run任意一个flutter命令(如flutter doctor等)时,它会下载它自己的依赖项并自行编译。
第一次可能会慢许多。以后再运行就会快得多。

Running results:
Insert image description here ·
Problem check + solution ideas:

  1. Flutter SDK 是否成功安装和配置环境变量?If ❌, repeat the previous steps to install and environment variables.

  2. 你的Windows系统版本是否是10以及以上?If ❌, please upgrade to Windows 10 or 11

  3. Android SDK工具是否符合要求?If ❌, please check the download of relevant tools in Android Studio:
    Insert image description here
    There may be a warning here, please run the relevant commands according to the prompts, and agree to the agreement:
    这个警告因为You do not agree to the agreement ,所以你需要运行一下它提示的这个命令同意一下协议:
    flutter doctor --android-licenses`

  4. 是否安装谷歌浏览器?If ❌, please install Chrome browser.

  5. 是否安装Visual studio?If ❌ and you need to develop desktop applications, please install it.

  6. 是否安装Androidl studio?If ❌, please install AS, but even if it is installed, you may still encounter a problem, that is, the Java path cannot be found:
    Android Studio cannot find the JAVA version (JDK version)

Insert image description here

Solution:
Copy the files in the JDK to the jre in the Android Studio installation directory:
Insert image description here
Insert image description here

  1. 是否有可连接的设备,比如Chrome等浏览器、Android模拟器、USB链接调试的Android手机等等If ❌, download + connect or connect later

  2. 网络资源能否正确获取?If ❌, it means that your image is not configured properly, or the image is currently unavailable.

Other questions you may encounter:

Using the JDK installer (exe), JDK environment variables are automatically configured. If there are multiple versions, you need to delete this under the system variable Path. (Otherwise it will be confusing)
Insert image description here


(4) Install Flutter and Dart plug-ins in Android Studio for easy use

Insert image description here
Now that you install Flutter, you will be prompted to install the Dart plug-in. If so 没提示, 自己搜索Dart插件install it.

Restart AS and you will see that you can 直接使用AScreate a new Flutter project:
Insert image description here


2. Create and run Flutter project

Note: When I made this record, it was August 2023. All versions were just downloaded, so if you use an old version, the interface may be different!

(1). Create a new Flutter project in Android Sudio

(2) Select flutter. You need to configure it for the first time flutter SDK. The path is the upper layer of the bin directory (that is flutter目录)

As shown in the picture:
Insert image description here

(3) Fill in the project information by yourself. The last reminder means:

(1) When created, the new project will run on the selected platforms (others can be added later). When
created, the new project will run on the selected platforms (others can be added later 可以稍后添加).
(2) Create project offline
creates a project offline, and does not require the Internet to download necessary resources such as Flutter sdk (make sure you have completed the installation, you do not need to check this)

(4) After creating a new project, the code is located in lib/main.dart.

(5) It runs very quickly on the browser, but is very slow on the mobile phone (the build took a long time but failed).

我第一次运行的时候出现一个问题,就是构建很久,似乎构建不出来。
Insert image description here

所以怀疑是gradle工具出错了(可能是之前新建项目,没构建成功,也就是gradle没下载完成,就手动强制退出AS了,导致工具不完整。)
我的解决办法是瞎弄出来的。我就是在插件市场,下载一个Gradle升级的辅助插件,然后自己科学上网,每次重启它会检查然后会自动把Gradle插件升级到最新了。
Insert image description here

在这个过程中发生一个扯淡的问题,就是我可能不小心把其他插件禁用掉了,导致新建项目的选项里没有Flutter项目。
网上说是把这玩意插件给禁了,重新打开就行了:
Insert image description here


3. Project structure + analysis sample code

(1) Some common knowledge:

1. Automatically align indents: right-click the Dart code area and select Reformat Code with dartfmt.
2.

(2) Code analysis:

1、引入一个库文件:
Import Material: It is a standard visual design language for mobile and web.
Flutter provides a rich set of Material widgets.

import 'package:flutter/material.dart';

2、入口函数main:
According to Dart syntax, it can be changed to
void main() => runApp(const MyApp());
Note: The main function uses the (=>) symbol, which is the abbreviation of a single-line function or method in Dart

void main() {
    
    
  runApp(const MyApp());
}

3、StatelessWidget无状态和StatefulWidget有状态
StatelessWidget is an immutable component class that represents a static user interface fragment. Its characteristic is that once created, its properties or status cannot be changed. It is typically used to display static content and does not require an interface that changes over time. For example, a simple text label or a static image can be created using a StatelessWidget.
·
StatefulWidget (stateful component): StatefulWidget is a mutable component class that represents a user interface fragment that can be re-rendered based on changes in internal state. Its characteristic is that it can contain variable states and attributes, and the interface can be dynamically updated according to changes in state. StatefulWidget is usually used for interfaces that need to respond to user interaction, data changes, or time changes. For example, a counter component can be created using a StatefulWidget, where the counter's value can be incremented or decremented based on user actions.
·
Note that many novices will misunderstand, 不可变where does this " " appear? We all know that a class generally contains two parts: 属性值+ 方法函数
which 属性值is used for description 这个类的属性状态. So what we are talking about is immutability 可变不可变in it . For example, there is one in one , this is . But components are tree-like, that is, component A may contain component B. Assume that component A is immutable and component B is mutable. This is okay, because it is immutable and is the attribute value of a certain component. It has nothing to do with other components (even the components you include). Many novices cannot grasp this change and find it difficult to understand. · Using the separation of StatelessWidget and StatefulWidget can bring some benefits:这个类中定义的变量值
继承自无状态的类变量a属性值a不可变的



(1) Rendering performance optimization: Since StatelessWidget is immutable, when the interface does not need to be re-rendered, Flutter can avoid unnecessary redraw operations, thus improving performance.
(2) State management: StatefulWidget allows you to manage state within the component. When the state changes, Flutter will automatically trigger re-rendering. This allows you to easily handle user interactions or data changes and update the interface in a timely manner.
(3) Component reuse: By separating the static part from the dynamic part of the interface, component reuse can be better achieved. You can define static interface structure in StatelessWidget, and then handle dynamic logic and state in StatefulWidget.
·
In short, StatelessWidget is used to represent static interface fragments, while StatefulWidget is used to represent dynamic interface fragments that need to be re-rendered according to state changes. This separation makes Flutter's interface construction more flexible, efficient, and easier to maintain.

// 1/3 不可变(无状态)
class MyApp extends StatelessWidget {
    
    
  const MyApp({
    
    super.key});
  // 1、变量属性值区域:此处没有。
  // This widget is the root of your application.
  // 这是一个widget(组件)
  // 这是你应用的根部组件(也就是第一个)
  // 2、函数方法区域:
  
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        // 这部分是应用的主题。
        //
        // TRY THIS: 
        // Try running your application with "flutter run". You'll see the application has a blue toolbar. 
        // 尝试运行你的应用(使用flutter run命令),就会看到应用上有一个深紫色的导航条
        // Then, without quitting the app,
        // try changing the seedColor in the colorScheme below to Colors.green
        // and then invoke "hot reload" (save your changes or press the "hot reload" button 
        // in a Flutter-supported IDE, or press "r" if you used the command line to start the app).
        // 它的就是想说,它支持热加载,你需要把下面的颜色改成Colors.green绿色,然后点击“热加载”按钮,也就是AS右上角的闪电按钮
        // 或者直接运行,就能够看到修改结果。意思就是不需要重新进行项目编译,这叫热加载。
        // Notice that the counter didn't reset back to zero; the application
        // state is not lost during the reload. To reset the state, use hot restart instead.
        // 注意,你在手机上点几下计数器,热加载以后,计数器并不会清零。也就是说,没有进行修改的部分在热加载过程中不会改变状态。
        // 如果你想改变状态,需要热重启替代。
        // This works for code too, not just values: Most code changes can be tested with just a hot reload.
        // 这也适用于代码,而不仅仅是值:大多数代码更改都可以通过热(重新)加载进行测试。热加载适合代码快速测试。
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),//这是一个有状态的组件,说明在无状态组件里,
      //是可以调用任何组件的,不区分有无状态。有无状态的组件说明的是,这个组件本身的属性,而别的组件的属性就不归它管了。
    );
  }
}
// 2/3  可变(有状态):其实就是需要重写一个方法。并使用这个方法来构建一个具有状态的对象。
class MyHomePage extends StatefulWidget {
    
    
  const MyHomePage({
    
    super.key, required this.title});

  /*
    This widget is the home page of your application. It is stateful, meaning that
    it has a State object (defined below) that contains fields that affect how it looks.
    这个小部件是应用程序的主页。它是有状态的,也就是说
    它有一个State对象(定义如下),其中包含影响其外观的字段。
  */

  /*
    This class is the configuration for the state. It holds the values (in this case the title)
    provided by the parent (in this case the App widget) and
    used by the build method of the State. Fields in a Widget subclass are always marked "final".
    这个类是状态的配置。它保存值(在本例中为标题)
    由父组件提供(在本例中是App小部件)和
    由该状态的构建方法使用。Widget子类中的字段总是被标记为“final”。
  */

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}
//  3/3------------------------------------------------
class _MyHomePageState extends State<MyHomePage> {
    
    
  int _counter = 0;

  void _incrementCounter() {
    
    
    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.
      调用setState来告诉Flutter框架,此状态中有东西发生了变化,
      这导致它重新运行下面的构建方法,以便显示可以反映更新的值。
      如果我们在没有调用setState()的情况下修改了_counter,那么build方法将不会再次被调用,因此什么也不会发生。
      */
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    
    
    /*This method is rerun every time setState is called, for instance as done
    by the _incrementCounter method above.
    每次调用setState时都会重新运行这个方法,例如上面的_incrementCounter方法。

    The Flutter framework has been optimized to make rerunning build methods
    fast, so that you can just rebuild anything that needs updating rather
    than having to individually change instances of widgets.
    Flutter框架经过优化,可以快速重新运行构建方法,这样你就可以重新构建任何需要更新的东西,而不必单独更改部件实例。
    */
    return Scaffold(
      appBar: AppBar(
        /*TRY THIS: Try changing the color here to a specific color (to
        Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
        change color while the other colors stay the same.
        试试这个:尝试将这里的颜色更改为特定的颜色(到Colors。可能是琥珀色?),并触发热重载,以看到应用栏改变颜色,而其他颜色保持不变。
        */
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        /*Here we take the value from the MyHomePage object that was created by
        the App.build method, and use it to set our appbar title.
        这里,我们从App.build方法创建的MyHomePage对象中获取值,并使用它来设置appbar标题。
        */
        title: Text(widget.title),
      ),
      body: Center(
        /*Center is a layout widget. It takes a single child and positions it
        in the middle of the parent.
        Center是一个布局部件。它接收一个子元素,并将其放置在父元素的中间。
        */
        child: Column(
          /*Column is also a layout widget. It takes a list of children and
          arranges them vertically. By default, it sizes itself to fit its
          children horizontally, and tries to be as tall as its parent.
          Column也是一个布局部件。它接收一个子元素列表,并将它们垂直排列。
          默认情况下,它会调整自己的大小以适应它的子元素,并尽量与父元素一样高。

          Column has various properties to control how it sizes itself and
          how it positions its children. Here we use mainAxisAlignment to
          center the children vertically; the main axis here is the vertical
          axis because Columns are vertical (the cross axis would be horizontal).
          列有各种属性来控制它自己的大小以及子元素的位置。这里我们使用mainAxisAlignment来让子元素垂直居中;
          这里的主轴是纵轴,因为列是垂直的(交叉轴是水平的)。

          TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
          action in the IDE, or press "p" in the console), to see the
          wireframe for each widget.
          试试这个:调用“debug painting”(在IDE中选择“Toggle debug Paint”操作,或者在控制台中按“p”),以查看每个部件的线框。
          */
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods。末尾的逗号使构建方法的自动格式化更好。.
    );
  }
}

4. Must-read e-book: "Flutter in Action·Second Edition"

5. Must-see official examples❌

You can go to github and search for flutter.
You will see:
Insert image description here>It is recommended to download a few more examples and run them around. Read more books and think more about practice. Basically you know how to use Flutter.
Insert image description here
Open the imported project, you may need to configure the Dart and Flutter paths.
Insert image description hereInsert image description here

Guess you like

Origin blog.csdn.net/zhinengxiong6/article/details/132515360