学习Flutter时需要了解的背景知识

news2024/11/15 12:28:28

关键词:Flutter、移动UI框架、跨平台、Widget、高效开发、自定义Widget、热重载、性能优化

摘要:Flutter是Google推出的开源移动UI框架,旨在支持高效构建高质量的原生应用,同时兼容iOS和Android平台。它通过热重载技术实现高效开发,使用自定义Widget满足复杂需求,并提供出色的性能和灵活的定制性。本文详细介绍了Flutter的背景知识,包括其产生的原因、历史发展、设计理念和Widget的组合与复用等,帮助读者全面了解Flutter框架的优势和应用。

阅读建议:对于想要了解Flutter或准备使用Flutter进行开发的读者,建议先了解其基本概念和设计理念,再逐步深入学习其具体的开发技术和实践。本文提供了丰富的背景知识和实例,有助于读者更好地理解和应用Flutter框架。

阅读时长:预计阅读时长为15-20分钟,具体时间根据个人阅读速度和理解能力而定。

 

目录

一、学习目标

1.深入理解Flutter产生的背景

1)推出Flutter的原因

早于Flutter的跨平台框架

React Native

Ionic

相对于React Native和Ionic来说Flutter的优势

高效的开发流程

出色的性能

灵活的定制性

跨平台兼容性

统一的开发体验

强大的社区支持

2)Flutter的历史发展

起源与研发(2015年)

首次亮相(2017年5月)

Beta版本与正式发布(2018年)

Beta版本

正式发布

Flutter for Web的推出

支持多平台与版本更新(2019年至今)

多平台支持

新特性引入

企业与开发者的认可

2.设计理念

1)一切皆为Widget的含义

UI元素的统一抽象

基础UI组件

高级组件和布局

页面布局和动画效果

抽象化的好处

2)灵活性和创造力的赋予

创造力的释放

开发过程的简化

3)Widget的组合与复用

Widget的组合

Widget的复用

4)自定义Widget的实现

二、学习资源

1.Flutter官方网站

2.相关博客文章

3.技术论坛

4.官方Dart软件包托管网站

1)pub.dev简介

2)pub.dev的核心优势

3)如何使用pub.dev


一、学习目标

1.深入理解Flutter产生的背景

Flutter是Google于2017年推出的开源移动UI框架,旨在帮助开发者通过一套代码库高效构建高质量的原生应用,同时支持iOS和Android两大移动平台。随着移动应用的普及和多平台开发需求的增加,传统的原生开发方式面临着开发成本高、维护难度大等问题。Flutter的出现,正是为了解决这些问题,提供一种更为高效、灵活的开发模式。

1)推出Flutter的原因

解决Android平台上的UI开发问题:Google最初着手研发Flutter的目标是为了解决Android平台上的UI开发问题。随着移动互联网的快速发展,用户对移动应用的需求日益增长,而传统的移动开发方式在某些方面已经无法满足高效、跨平台和统一UI的需求。因此,Google决定推出一款全新的移动UI框架,以提高开发效率和用户体验。

早于Flutter的跨平台框架

在推出Flutter之前,主流移动端跨平台开发框架主要包括React Native、Ionic等。这些框架各有其优缺点,具体如下:

React Native

优点

  1. 跨平台性:React Native允许开发者使用同一套代码库来开发iOS和Android应用,显著提高了开发效率和代码复用率。

  2. 性能优化:React Native的部分代码是通过JavaScriptCore来执行的,而且在某些情况下,它可以通过Hermes引擎优化启动时间,减少内存占用。

  3. 丰富的第三方库支持:React Native拥有庞大的社区支持和丰富的第三方库资源,为开发者提供了更多的便利和灵活性。

缺点

  1. 性能差距:尽管React Native在不断优化,但在某些方面,如CPU和图形渲染,其性能可能仍然不及原生应用。

  2. 学习曲线:对于不熟悉React的开发者来说,React Native可能具有一定的学习难度。

  3. 通信延迟:JavaScript与原生之间的通信可能会导致卡顿现象,尤其是在复杂的应用场景中。

Ionic

优点

  1. Web技术栈:Ionic允许开发者使用熟悉的Web技术(HTML、CSS、JavaScript)来开发移动应用,降低了学习成本。

  2. 跨平台性:与React Native类似,Ionic也支持跨平台开发,提高了开发效率和代码复用率。

  3. 插件支持:Ionic提供了丰富的插件库,可以帮助开发者快速实现各种功能。

缺点

  1. 性能问题:由于Ionic是基于Web技术的,因此在性能方面可能不如原生应用或某些其他跨平台框架。

  2. 原生功能限制:Ionic可能无法充分利用所有原生API,这意味着开发者可能无法实现一些特定于平台的功能。

相对于React Native和Ionic来说Flutter的优势
  • 高效的开发流程

Flutter采用热重载技术,使得开发者可以实时看到代码更改的效果,从而大大缩短了开发周期,并提高了开发效率。这种快速迭代开发的能力是Flutter的一大优势。

  • 出色的性能

Flutter使用自己的渲染引擎,提供了极快的渲染速度和响应性能。这意味着用户可以享受到流畅、高效的用户体验,满足了对高效、流畅体验的需求。

  • 灵活的定制性

Flutter允许开发者通过自定义小部件来构建任何类型的用户界面,这种高度的灵活性使得Flutter能够满足各种复杂的应用需求。

  • 跨平台兼容性

Flutter支持iOS、Android、Web、Windows、macOS和Linux等多个平台,这种广泛的平台支持使得开发者能够使用相同的代码库和开发工具,降低了学习和部署成本。

  • 统一的开发体验

无论是在Android还是iOS上进行开发,Flutter都提供了相同的API和开发工具,这有助于减少开发人员的学习成本,并提高了代码的复用性。

  • 强大的社区支持

Flutter拥有一个活跃的社区,为开发者提供了大量的第三方库和组件,这些资源可以扩展Flutter的功能,进一步提高了开发效率和应用的丰富性。

2)Flutter的历史发展

  • 起源与研发(2015年)

Google在2015年开始着手研发Flutter,旨在解决Android平台上的UI开发问题。

  • 首次亮相(2017年5月)

Flutter在Google I/O大会上首次亮相,成为了该大会的一大亮点。这标志着Google正式推出了这款跨平台的移动应用开发框架。

  1. 需求驱动:随着移动互联网的快速发展,移动应用的开发需求日益增长。然而,传统的移动开发方式在某些方面已经无法满足高效、跨平台和统一UI的需求。特别是在Android平台上,UI开发问题逐渐凸显,急需一种新的解决方案来提高开发效率和用户体验。这正是Google开始研发Flutter的初衷。

  2. 内部孵化:Flutter最初是Google内部孵化的一个项目,名为Sky。在内部研发过程中,Google发现这一框架具有巨大的潜力,能够解决当前移动开发面临的一些核心问题。

  3. 开源与命名:经过一年的内部研发,2015年10月,这个项目正式更名为Flutter,并在GitHub上开源。这一举措旨在吸引更多的开发者参与进来,共同推动Flutter的发展。

  4. 跨平台特性:从一开始,Flutter就被设计为跨平台的UI框架。它不仅能够解决Android平台上的UI开发问题,还能够支持iOS等其他平台。这种跨平台特性使得Flutter具有更广泛的应用前景。

Flutter的起源可以追溯到2015年Google为解决Android平台上的UI开发问题而开始的研发工作。经过内部孵化和一年的研发,最终形成了这个具有跨平台特性的UI框架,并在同年开源,以吸引更多开发者的参与和贡献。

  • Beta版本与正式发布(2018年)

2018年,Flutter进入了Beta版本,并在同年的Google I/O大会上发布了Flutter 1.0版本,正式宣布上线。此外,Flutter开发团队还推出了Flutter for Web,允许开发者将Flutter应用直接部署到Web端。

  • Beta版本
    • 进入Beta阶段:在2018年,经过一段时间的研发和测试,Flutter终于进入了Beta版本阶段。这意味着框架已经趋于稳定,并准备进行更广泛的测试和应用。
    • 功能完善:在Beta版本期间,Flutter开发团队继续对框架进行优化和完善,确保其稳定性和性能达到预定标准。这为后续的正式发布奠定了坚实的基础。
  • 正式发布
    • Google I/O大会发布:在2018年的Google I/O大会上,Flutter 1.0版本被正式发布。这是一个重要的里程碑,标志着Flutter已经成熟并准备好供开发者广泛使用。
    • 版本特点:Flutter 1.0版本提供了丰富的UI组件和动画效果,支持自定义UI,使得开发者可以根据自己的需求构建独特的用户界面。同时,该版本还注重稳定性和bug修复,为开发者提供了更加可靠的开发环境。
  • Flutter for Web的推出
    • Web端支持:除了移动平台外,Flutter开发团队还推出了Flutter for Web。这一功能允许开发者将使用Flutter开发的应用直接部署到Web端,进一步扩展了Flutter的应用场景。
    • 技术实现:Flutter for Web通过使用Skia图形引擎和Dart编程语言来实现高效的渲染和流畅的用户体验。这使得开发者能够利用Flutter的强大功能来构建高性能的Web应用。
  • 支持多平台与版本更新(2019年至今)

2019年,Flutter 2.0版本发布,正式支持Web、Windows、macOS等多个平台。此后,Flutter开发团队继续推出了多个版本,包括Flutter 2.2和Flutter 2.5等,不断引入新特性,如Null safety、Flutter for Chrome OS等。同时,Flutter也得到了越来越多的企业和开发者的认可和使用。

  • 多平台支持
  1. Flutter 2.0的发布:在2019年,Flutter迎来了2.0版本的发布。这个版本的重要性在于它正式支持了Web、Windows、macOS等多个平台。这意味着开发者可以使用Flutter来开发跨平台的应用程序,大大提高了开发效率和代码复用性。

  2. 多版本迭代与更新:随后,Flutter开发团队继续推出了多个重要版本,如Flutter 2.2和Flutter 2.5等。这些版本不仅修复了之前的bug,还引入了许多新特性,使得Flutter的功能更加丰富和完善。

  • 新特性引入
  1. Null safety:在Flutter中,Null safety(空安全)是Dart 2.12版本引入的一个重要特性,它允许开发者在代码中明确哪些变量可以为null,哪些不能为null。这有助于在编译时期就捕捉到可能的空引用错误,从而增强代码的健壮性。

以下是一个简单的Flutter代码示例,展示了如何在Dart中使用Null safety特性:

import 'package:flutter/material.dart';  
  
void main() {  
  runApp(MyApp());  
}  
  
class MyApp extends StatelessWidget {  
  @override  
  Widget build(BuildContext context) {  
    return MaterialApp(  
      home: Scaffold(  
        appBar: AppBar(  
          title: Text('防止空值引用异常的栗子'),  
        ),  
        body: Center(  
          child: MyNullableWidget(),  
        ),  
      ),  
    );  
  }  
}  
  
// 定义一个可以为null的String类型变量  
class MyNullableWidget extends StatelessWidget {  
  String? nullableString; // 这个变量可以为null  
  
  MyNullableWidget({this.nullableString});  
  
  @override  
  Widget build(BuildContext context) {  
    // 使用空值合并运算符 ?? 来提供一个非空默认值  
    String textToShow = nullableString ?? 'hello world!';  
  
    // 使用if-null运算符 ??= 来在变量为null时赋予新值  
    nullableString ??= 'hello world';  
  
    // 在Dart的空安全版本中,如果nullableString确定不为null,可以使用!后缀来断言  
    // String nonNullableText = nullableString!; // 仅在确定nullableString不为null时使用  
  
    return Column(  
      mainAxisAlignment: MainAxisAlignment.center,  
      children: <Widget>[  
        Text('可空字符串: $textToShow'),  
        // Text('非可空字符串: $nonNullableText'), // 如果使用了上面的断言  
      ],  
    );  
  }  
}

在这个例子中,MyNullableWidget 类有一个可以为空的string类型成员变量nullableString。在build方法中,我们使用了空值合并运算符??来确保在nullableString为空时有一个默认值。同时,我们也展示了如何使用??=运算符来给nullableString赋初值(如果它原本是null)。

请注意,如果你确定某个可为null的变量在特定上下文中不为null,你可以使用!后缀来断言该变量非空。然而,在实际编程中应谨慎使用此操作,因为它会在运行时抛出NullReferenceException,如果变量实际上为null的话。

  1. Flutter for Chrome OS等新平台支持:随着技术的不断发展,Flutter还逐渐支持了更多平台,如Chrome OS等。这使得Flutter的应用场景更加广泛,满足了不同平台和设备上的开发需求。

  • 企业与开发者的认可
  1. 企业支持:越来越多的企业开始采用Flutter进行应用开发。这不仅证明了Flutter的稳定性和高效性,也显示了其在企业级应用中的广泛适用性。

  2. 开发者社区的增长:随着Flutter的不断发展,其开发者社区也在不断扩大。越来越多的开发者选择使用Flutter来构建应用程序,这得益于其跨平台特性和丰富的功能支持。

2.设计理念

Flutter的设计理念是“一切皆为Widget”。这意味着在Flutter中,无论是简单的按钮、文本框,还是复杂的页面布局和动画效果,都是由Widget组成的。这种设计理念赋予了开发者极大的灵活性和创造力,使得他们可以通过组合不同的Widget来快速构建出丰富多样的用户界面。

1)一切皆为Widget的含义

在Flutter中,“一切皆为Widget”意味着所有的UI元素,无论大小、复杂程度,都被视为Widget。这包括了基础的UI组件,如按钮、文本框、图片等,也包括了更高级的组件,如列表、网格布局,甚至是整个页面的布局和复杂的动画效果。这种设计将UI构建的过程抽象化,使得开发者能够以统一的方式来处理各种UI元素。

  • UI元素的统一抽象

“一切皆为Widget”意味着在Flutter中,所有的UI元素,不论其大小、功能或复杂程度,都被统一抽象为Widget。这种抽象化处理方式为开发者提供了一种简洁、一致的接口来创建和管理UI。

  • 基础UI组件

基础的UI组件,如按钮(Button)、文本框(TextField)、图片(Image)等,在Flutter中都是作为Widget来实现的。这些基础组件是构建更复杂UI的基石,它们自身也是由更简单的Widget组合而成。

  • 高级组件和布局

除了基础组件外,更高级的UI元素,如列表(ListView)、网格布局(GridLayout)等,同样被视为Widget。这些高级组件在内部可能包含了多个基础Widget,通过组合和布局来实现更复杂的功能和视觉效果。

  • 页面布局和动画效果

在Flutter中,整个页面的布局也是由Widget来定义的。通过嵌套和组合不同的Widget,开发者可以轻松地构建出复杂的页面结构。此外,动画效果也是通过特定的Widget来实现的,这些Widget可以在时间轴上控制其他Widget的属性和行为,从而实现丰富的动画效果。

  • 抽象化的好处

将UI构建过程抽象化为Widget带来了诸多好处。首先,它简化了开发过程,因为开发者只需要熟悉一套统一的接口就可以处理所有类型的UI元素。其次,这种抽象化提高了代码的可读性和可维护性,因为所有的UI逻辑都被封装在Widget中,便于理解和修改。最后,Widget的复用性也使得开发更加高效,一个精心设计的Widget可以在多个地方重复使用,减少了重复劳动。

2)灵活性和创造力的赋予

这一设计理念为开发者提供了极大的灵活性和创造力。由于所有的UI都是基于Widget构建的,开发者可以通过组合、嵌套和自定义Widget来快速构建出独特且功能丰富的用户界面。这种模块化的设计方式不仅简化了开发过程,还使得界面的修改和维护变得更加容易。

灵活性还体现在对不同屏幕尺寸和分辨率的适应性上。由于Widget可以动态地调整其大小和布局,因此开发者可以轻松地创建出响应式的用户界面,以适应不同设备和屏幕尺寸。

  • 创造力的释放

“一切皆为Widget”的设计理念也极大地激发了开发者的创造力。通过自定义Widget,开发者可以实现独特的视觉效果和交互体验。例如,他们可以创建一个自定义的动画Widget,以在界面中实现独特的过渡效果或动态展示。或者,他们可以设计一个具有特定功能的Widget,如一个能够实时显示数据的图表Widget。

此外,由于Widget之间的独立性,开发者可以自由地替换、更新或扩展特定的Widget,而无需对整个界面进行大规模的修改。这种模块化的设计方式不仅降低了开发的复杂性,还鼓励开发者进行创新和实验。

  • 开发过程的简化

通过将UI元素抽象为Widget,开发者可以更加专注于实现特定的功能和视觉效果,而无需过多关注底层的渲染和布局细节。这种抽象化不仅简化了开发过程,还使得代码更加清晰、易于维护。

同时,由于Widget之间的解耦性,当需要对界面进行修改或维护时,开发者可以精确地定位到需要更改的Widget,而无需对整个系统进行大规模的调整。这不仅提高了开发效率,还降低了出错的可能性。

“一切皆为Widget”的设计理念通过提供灵活性和创造力,使开发者能够更快速、更高效地构建出独特且功能丰富的用户界面。这种模块化的设计方式简化了开发过程,降低了维护成本,并鼓励开发者进行创新和实验。因此,这一理念在提升用户体验和推动应用创新方面发挥了重要作用。

3)Widget的组合与复用

在Flutter中,开发者可以通过组合不同的Widget来实现复杂的页面布局和功能。例如,一个复杂的列表页面可以由多个简单的Widget(如列表项、分隔线、图片等)组合而成。这种组合方式不仅提高了代码的可读性和可维护性,还使得界面的更新和重构变得更加灵活。同时,由于Widget的独立性,它们可以很容易地在不同的页面和项目中复用,从而提高了开发效率。

  • Widget的组合

Flutter中的Widget设计得非常模块化,这意味着开发者可以通过组合多个简单的Widget来创建复杂的UI。例如,一个复杂的列表页面可能包含多个列表项Widget、分隔线Widget、图片Widget等。

以下是一个简单的Flutter页面,其中组合了ListViewListTile(列表项Widget)、Divider(分隔线Widget)来创建一个列表页面。

import 'package:flutter/material.dart';  
  
void main() {  
  runApp(MyApp());  
}  
  
class MyApp extends StatelessWidget {  
  @override  
  Widget build(BuildContext context) {  
    return MaterialApp(  
      home: Scaffold(  
        appBar: AppBar(  
          title: Text('Widget 组件的小栗子'),  
        ),  
        body: ListView(  
          children: <Widget>[  
            ListTile(  
              title: Text('Item 1'),  
              subtitle: Text('这是第一个'),  
            ),  
            Divider(),  
            ListTile(  
              title: Text('Item 2'),  
              subtitle: Text('这是第二个'),  
            ),  
            Divider(),  
            // ... 可以继续添加更多的ListTile和Divider  
          ],  
        ),  
      ),  
    );  
  }  
}

界面效果如下:
 

在这个例子中,ListView Widget包含了多个ListTileDivider Widget,通过组合这些简单的Widget,我们构建了一个具有多个列表项的页面。

  • Widget的复用

在Flutter中,由于每个Widget都是独立的、可复用的组件,因此它们可以很容易地在不同的页面和项目中被重复使用。

假设我们有一个自定义的ReusableCard Widget,它可以在多个页面中被复用。

import 'package:flutter/material.dart';  
  
class ReusableCard extends StatelessWidget {  
  final String title;  
  final String description;  
  
  ReusableCard({required this.title, required this.description});  
  
  @override  
  Widget build(BuildContext context) {  
    return Card(  
      child: Column(  
        children: <Widget>[  
          ListTile(  
            title: Text(title),  
            subtitle: Text(description),  
          ),  
        ],  
      ),  
    );  
  }  
}

这样,我们可以在不同的页面中复用ReusableCard Widget: 

import 'package:flutter/material.dart';  
import 'reusable_card.dart'; // 引入自定义的ReusableCard Widget  
  
void main() {  
  runApp(MyApp());  
}  
  
class MyApp extends StatelessWidget {  
  @override  
  Widget build(BuildContext context) {  
    return MaterialApp(  
      home: Scaffold(  
        appBar: AppBar(  
          title: Text('Widget复用的栗子'),  
        ),  
        body: Column(  
          children: <Widget>[  
            ReusableCard(title: '我是一个卡片', description: '同一个Widget的第一个复用的实例'),  
            ReusableCard(title: '我也是一个卡片', description: '同一个Widget的第二个复用的实例'),  
            // ... 可以在此继续添加更多的ReusableCard实例  
          ],  
        ),  
      ),  
    );  
  }  
}

界面效果:
 

由此可见这种复用性减少了代码的重复编写,提高了开发效率。 

4)自定义Widget的实现

除了使用Flutter提供的现有Widget外,开发者还可以根据自己的需求创建自定义Widget:自定义Widget的实现主要通过继承现有的Widget类或组合多个Widget来完成,这样可以定义出具有特定功能、布局或样式的Widget,以满足项目的特定需求。

举个栗子:

创建一个名为CustomButton的Widget,它继承自FlatButton(或在新版本的Flutter中使用ElevatedButton等),并添加了一些自定义的样式和行为:

import 'package:flutter/material.dart';    
  
// 自定义的按钮Widget  
class CustomButton extends StatelessWidget {  
  final VoidCallback onPressed; // 按钮点击时的回调函数  
  final String text; // 按钮上显示的文本  
  
  // 构造函数,使用命名参数,确保调用时必须提供onPressed和text参数  
  CustomButton({required this.onPressed, required this.text});  
  
  @override  
  Widget build(BuildContext context) {  
    return ElevatedButton(  
      style: ButtonStyle(  
        backgroundColor: MaterialStateProperty.all(Colors.blue), // 自定义背景颜色,所有状态下均为蓝色  
        foregroundColor: MaterialStateProperty.all(Colors.white), // 自定义文字颜色,所有状态下均为白色  
        padding: MaterialStateProperty.all(EdgeInsets.symmetric(horizontal: 20, vertical: 10)), // 自定义内边距,水平方向20,垂直方向10  
      ),  
      onPressed: onPressed, // 设置点击事件,使用构造函数传入的onPressed回调  
      child: Text(text), // 设置按钮文本,使用构造函数传入的text  
    );  
  }  
}

 这段代码定义了一个自定义的按钮CustomButton,它继承自StatelessWidget。按钮有两个属性:onPressed(点击时的回调函数)和text(按钮上显示的文本)。在build方法中,使用了ElevatedButton来创建一个具有特定样式和行为的按钮。按钮的样式通过ButtonStyle进行自定义,包括背景颜色、文字颜色和内边距。点击事件通过onPressed属性设置,按钮文本通过Text组件设置。

二、学习资源

1.Flutter官方网站

Flutter官方网站(Flutter - Build apps for any screen)是获取Flutter最新信息、学习资源和文档的首选途径。网站提供了详细的安装指南、教程、API文档和示例代码等资源,帮助开发者快速上手Flutter开发。

2.相关博客文章

互联网上有大量关于Flutter的博客文章,涵盖了从入门到进阶的各个方面。这些文章通常由经验丰富的开发者撰写,分享了他们在Flutter开发过程中的实践经验、技巧心得和解决方案。例如,CSDN博客(CSDN博客 - 专业IT技术发表平台)上就汇集了大量优质的Flutter教程和案例分享。

3.技术论坛

技术论坛如Stack Overflow(Stack Overflow - Where Developers Learn, Share, & Build Careers)和Reddit的Flutter社区也是学习Flutter的重要资源。在这些论坛上,开发者可以提出自己遇到的问题并寻求解答,也可以分享自己的经验和见解。通过参与论坛讨论,开发者可以不断拓宽自己的知识面和视野。

4.官方Dart软件包托管网站

除了Flutter官方网站、相关博客文章和技术论坛外,pub.dev也是Flutter学习过程中不可或缺的学习资源。

1)pub.dev简介

pub.dev(The official repository for Dart and Flutter packages.)是由Google维护的Dart软件包托管网站,专为Dart和Flutter开发者提供全面的包发现、下载和分发服务。这个网站不仅是一个静态资源库,还包含了完整的开发、版本管理和搜索机制,旨在为开发者构建高效且易用的生态环境。

2)pub.dev的核心优势

  1. 高质量的包资源:pub.dev上汇聚了大量由全球开发者贡献的高质量软件包,涵盖了UI组件、工具库、网络请求、数据库操作等多个方面,为Flutter开发者提供了丰富的选择。

  2. 强大的搜索功能:pub.dev提供了强大的搜索功能,开发者可以根据关键词、作者、标签等多种条件快速找到所需的包。此外,网站还引入了评分体系,包括‘赞’、‘Pub 分值’和‘热门度’,帮助开发者评估包的质量和受欢迎程度。

  3. 版本管理与依赖追踪:pub.dev支持对软件包不同版本的有效管理,开发者可以方便地查看包的更新日志、依赖关系,并进行版本回滚等操作,确保项目的稳定性和可维护性。

  4. 社区驱动:pub.dev面向开放的Dart和Flutter社区,所有开发者都能参与到包的评价和反馈中。这种社区驱动的模式不仅促进了代码质量的持续提升,还为开发者提供了一个交流和学习的平台。

3)如何使用pub.dev

  1. 查找和引入包:开发者可以在pub.dev上搜索所需的包,查看其详细信息、评分、文档和示例代码。找到合适的包后,可以在Flutter项目的pubspec.yaml文件中添加包的依赖项,并通过运行flutter pub get命令来安装这些包。

  2. 发布自己的包:对于想要分享自己开发的Flutter包的开发者来说,pub.dev也提供了便捷的发布渠道。开发者只需要遵循网站的发布指南,上传自己的包,并填写相关信息即可。一旦审核通过,其他开发者就可以在pub.dev上找到并使用这些包了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2047224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【机器人学】7-1.六自由度机器人自干涉检测-总体算法介绍

目录 前言 机器人自干涉检测方法 一 机械臂各连杆等效 二 确定一个圆柱体 三 圆柱体的空间变换 四 空间几何分析 五 关键点总结 前言 机器人在运行过程中&#xff0c;可能发生碰撞&#xff0c;碰撞物可以是外界物体&#xff0c;也可以是机器人自己的关节间发生碰撞…

Docker部署Eclipse Mosquitto开源MQTT的消息代理环境步骤(实践)

1.前言 Eclipse Mosquitto是一个开源&#xff08;EPL/EDL许可&#xff09;的消息代理&#xff0c;实现了MQTT协议的版本5.0、3.1.1和3.1。Mosquitto是轻量级的&#xff0c;适用于从低功耗单板计算机到完整服务器的所有设备。 MQTT协议提供了一种轻量级的消息传输方法&#xf…

渗透测试-行业术语

1.肉鸡 肉鸡用来比喻哪些可以随意被我们控制的计算机&#xff0c;可以是普通的个人电脑&#xff0c;也可以是大型服务器或者其他网络设备&#xff0c;我们可以像操作自己的电脑一样操作他们而不被发觉。 2.木马 表面上伪装成了正常程序&#xff0c;但是当程序被运行的时候&a…

【gitlab】gitlab-ce:17.3.0-ce.0 1:使用docker engine安装

ce版本必须配置代理。 极狐版本可以直接pull 社区版GitLab不支持Alibaba Cloud Linux 3,本操作以Ubuntu/Debian系统为例进行说明,其他操作系统安装说明,请参见安装社区版GitLab。 docker 环境重启 sudo systemctl daemon-reload sudo systemctl restart docker脚本安装 安裝…

趣味算法------约瑟夫环

目录 问题概述&#xff1a; 问题解析&#xff1a; 图文示意&#xff1a; 处决开始&#xff1a; 第一轮结束&#xff1a; 第二轮结束&#xff1a; 最后一轮&#xff1a; 寻找规律&#xff1a; 最终思路&#xff1a; 具体代码&#xff1a; 总结&#xff1a; 问题概述&…

【Pytorch02】开发环境准备

开发环境准备 安装教程 视频 开发环境 Python 3.7 Anaconda 3.5.1CUDA 10.0Pycharm Community 检测是否安装完毕 conda --version # 检查Anaconda是否安装完毕 nvcc -V # 检查CUDA是否安装完毕

ES-分布式搜索引擎

DSL查询文档 精确查询 、 我附近的人 实例 根据页码跳转无法使用 高亮

Flandre Scarlet的精致蕾丝上半身造型,金发飘逸

Flandre Scarlet戴zun帽&#xff0c;上半身细节极其精致的蕾丝装饰&#xff0c;面带微笑&#xff0c;双臂自然下垂&#xff0c;金色头发飘逸。 正向提示词 Flandre Scarlet,zun hat,extremely detailed lace,:) , upper body,arms at sides,lace,golden hairFlandre Scarlet&…

AI学习记录 - transformers的decoder和encoder中的自注意力矩阵和掩码矩阵的数据处理

掩码掩码&#xff0c;指的是掩盖住后面的词汇的词向量对我当前词汇造成影响。把PAD字符设置成负无穷大&#xff0c;概念上不叫掩码&#xff0c;只是计算方式和掩码一样。 怎么生成掩码&#xff0c;在非掩码注意力矩阵中&#xff0c;把PAD词向量每个维度设置成负无穷大&#xf…

基于web框架的协同过滤的美食推荐系统【数据爬虫、管理系统、数据可更新、样式可调整】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍研究背景研究的目的与意义协同过滤算法基于用户的协同过滤算法定义基于物品的协同过滤算法的定义 数据库设计db_food&#xff08;美食信息表&#xff09;db_collect&#xff08;美食…

加载torch报错及如何解决

Failed to import pytorch fbgemm.dll or one of its dependencies is missing. 这往往是你的电脑缺少了某些微软的dll文件。所以报错了。 解决办法 前往https://www.dllme.com/dll/files/libomp140_x86_64?sortupload&arch0x8664 点击。 按照你的电脑是否为64位进行选择…

vue3-03-创建响应式数据的几种方法

响应式数据 一、 ref 创建&#xff1a;响应式数据1&#xff09;ref 创建&#xff1a;基本类型的响应式数据2&#xff09;ref 创建&#xff1a;对象类型的响应式数据3&#xff09;volar 插件自动添加 .value4&#xff09;customRef 自定义 ref 二、 reactive 创建&#xff1a;响…

联想2025校招 技术研究方向试卷

目录 1. 第一题2. 第二题 ⏰ 时间&#xff1a;2024/08/16 &#x1f504; 输入输出&#xff1a;ACM格式 ⏳ 时长&#xff1a;1.5h 本试卷还有选择题部分&#xff0c;但这部分比较简单就不再展示。 1. 第一题 题目描述 小明正在神奇苹果园里工作。这个苹果园里一共有 n n n 棵…

C#堆排序算法

前言 堆排序是一种高效的排序算法&#xff0c;基于二叉堆数据结构实现。它具有稳定性、时间复杂度为O(nlogn)和空间复杂度为O(1)的特点。 堆排序实现原理 构建最大堆&#xff1a;将待排序数组构建成一个最大堆&#xff0c;即满足父节点大于等于子节点的特性。将堆顶元素与最后…

海康VisionMaster使用学习笔记4-快速匹配模块

快速匹配模块 快速匹配包括基本参数,特征模板,运行参数,结果显示 基本参数 可以修改图像源和模块的ROI区域. 特征模版 可以配置管理所有的模版,点击创建可以新增模版,也可以通过载入加载本地的模型 建立新模版 点击创建,可以选择当前图像或本地图像进行建模 模版存图按…

【ASFF】《Learning Spatial Fusion for Single-Shot Object Detection》

arXiv-2019 https://github.com/GOATmessi7/ASFF 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method4.1 Strong Baseline4.2 Adaptively Spatial Feature Fusion4.2.1 Feature Resizing4.2.2 Adaptive Fusion 4.3 Consistency Propert…

DVWA | CSRF(LowMedium)攻击的渗透实践

目录 概述 Low Medium 概述 CSRF&#xff08;Cross-Site Request Forgery&#xff0c;跨站请求伪造&#xff09; 是一种网络攻击方式。 通过伪造当前用户的行为&#xff0c;让目标服务器误以为请求由当前用户发起&#xff0c;并利用当前用户权限实现业务请求伪造。 例如&a…

如何将excel以文本形式储存的数字一键转换为数字

有时候一些软件给出的数据格式很恶心&#xff0c;为了方便计算常常以数字粘贴到新表&#xff0c;但随之而来新问题&#xff0c;以文本储存的公式无法用公式计算&#xff0c;怎么办啊 方法一&#xff1a;使用“转换为数字”功能 (对数字少时用&#xff09; 当Excel检测到某个单…

得到任务式 大模型应用开发学习方案

根据您提供的文档内容以及您制定的大模型应用开发学习方案&#xff0c;我们可以进一步细化任务式学习的计划方案。以下是具体的任务式学习方案&#xff1a; 任务设计 初级任务 大模型概述&#xff1a;阅读相关资料&#xff0c;总结大模型的概念、发展历程和应用领域。深度学…

STM32定时器输入捕获功能

用于测频率测占空比 IC(Input Capture)输入捕获 输入捕获模式下&#xff0c;当通道输入引脚出现指定电平跳变&#xff08;上升沿/下降沿&#xff09;时&#xff0c;会让当前CNT的值将被锁存到CCR中&#xff0c;可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数…