Flutter入门——创建第一个Flutter项目
Flutter入门——创建第一个Flutter项目
一、创建项目
第一个项目使用Android Studio创建,步骤如下:
-
先打开Android Studio,会有一个创建新的Flutter应用的选项
-
选择Flutter应用
-
填写相关应用设置
-
项目目录介绍
-
Android
这里Android平台相关文件,这里基本上和创建的原生Android程序文件类似,但是个别文件会有所不同。它主要包括Gradle的配置、App图标、名称、版本号、起始页以及Android平台的权限申请等Android方面的配置。
-
IOS
同理,IOS平台相关文件
-
lib
存放包括Flutter程序主入口文件main.dart的文件夹,简单来说此文件夹就是我们.dart代码的存放位置。
mian文件以及入口方法放到下面解释
-
web
-
pubspec.yaml
环境配置文件,此文件为yaml文件
-
-
main.dart分析
代码:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key}) : super(key: key); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override void initState() { // TODO: implement initState super.initState(); } @override void dispose() { // TODO: implement dispose super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("第一个Flutter项目"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( '$_counter', style: Theme.of(context).textTheme.display1, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } }
void main() =>runApp(MyApp());
这里就是Flutter的入口函数,当函数体里只有一行代码时,可以直接使用=>
来省略{}
,,否则需要使用大括号。
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
这里创建了一个MaterialApp的App,而Flutter中的MaterialApp则是一个MaterialApp Design设计理念的入口Widget,里面包含了Material风格所需要的控件,例如本实例中的title、theme和home等。其中home则是应用程序默认显示在屏幕的界面,也就是说MyHomePage才是整整显示在屏幕上的界面。
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("第一个Flutter项目"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
这里我们创建一个StatefulWidget,在Flutter中组件分为有状态组件和无状态组件
- StatefulWidget : 具有可变状态的窗口部件,具有完整的生命周期,在实际使用过程中可以刷新组件状态
- StatelessWidget:不可变状态窗口部件,在实际使用过程中可以刷新组件状态
在创建有状态组件是还需要创建一个状态类与组件绑定,例如_MyHomePageState就是_MyHomePage的状态类。这里重写了initState、dispose和build方法,initstate是组件初始化时候调用的方法,build主要就是状态改变是调用的方法,通过调用build方法来对组件进行渲染,dispose则是组件销毁时调用的方法。在build中返回了一个Scaffold,Scaffold 是 Material library 中提供的一个widget, 被称为软件脚手架,它提供了默认的导航栏、标题和包含主屏幕widget树的body属性。通过此实例我们可以看到flutter组件的嵌套逻辑,在Scaffold中添加了AppBar,也就是App上端的部分,body就是屏幕中间的主要内容部分,还可以添加bottomNavigationBar底部导航栏。
body属性为一个布局Widget Center,他是一个居中布局的Widget,其中又嵌套了一个column垂直布局的布局组件,column组建中有个内容为_counter变量的文本组件Text,其中_counter是可以改变的,也就是点击FloatingActionButton按钮可以实现+1操作。
Flutter更多的组件内容可以通过Flutter中文网等网站学习,也可以通过网上的视频学习,这里推荐技术胖的免费视频:https://jspang.com/detailed?id=58
二、Flutter打包(以Android为例)
-
首先配置AndroidMamifest.xml应用清单,路径在Android->app->src->main
- mipmap-hdpi - 72*72
- mipmap-mdpi - 48*48
- mipmap-xhdpi - 96*96
- mipmap-xxhdpi - 144*144
- mipmap-xxxhdpi - 192*192
-
build配置,主要设置appid、版本号以及指定对应的API级别,路径在Android->app->build.gradle
-
添加启动页
-
生成key
keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
其中~/key.jks制定了key存放的位置,根据自己的需求放置到一个相对安全的文件夹中保存
F:\flutter\projects\flutter_demo>keytool -genkey -v -keystore f://key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key 输入**库口令: 再次输入新口令: 您的名字与姓氏是什么? [Unknown]: 您的组织单位名称是什么? [Unknown]: 您的组织名称是什么? [Unknown]: 您所在的城市或区域名称是什么? [Unknown]: 您所在的省/市/自治区名称是什么? [Unknown]: 该单位的双字母国家/地区代码是什么? [Unknown]: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown是否正确? [否]: y 正在为以下对象生成 2,048 位RSA**对和自签名证书 (SHA256withRSA) (有效期为 10,000 天): CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown 输入 <key> 的**口令 (如果和**库口令相同, 按回车): [正在存储f://key.jks] Warning: JKS **库使用专用格式。建议使用 "keytool -importkeystore -srckeystore f://key.jks -destkeystore f://key.jks -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。
根据情况自行填写应用信息。
创建成功之后还需要下Android目录下创建key.peoperties文件,内容包括如下
#生成时设置的密码 storePassword=123456789 keyPassword=123456789 keyAlias=key #key存放地址 storeFile=f:/key.jks
还需要在gradle中配置签名,gradle位置在Android->app->build.gradle
替换:
android {
为:
def keystorePropertiesFile = rootProject.file("key.properties") def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android {
替换:
buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug } }
为:
signingConfigs { release { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile file(keystoreProperties['storeFile']) storePassword keystoreProperties['storePassword'] } } buildTypes { release { signingConfig signingConfigs.release } }
在这里尤其需要注意字段名称是否相同。
-
构建打包app
执行命令进行打包,这是发布版的应用程序已经打包完成
F:\flutter\projects\flutter_demo> flutter build apk You are building a fat APK that includes binaries for android-arm, android-arm64. If you are deploying the app to the Play Store, it's recommended to use app bundles or split the APK to reduce the APK size. To generate an app bundle, run: flutter build appbundle --target-platform android-arm,android-arm64 Learn more on: https://developer.android.com/guide/app-bundle To split the APKs per ABI, run: flutter build apk --target-platform android-arm,android-arm64 --split-per-abi Learn more on: https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split Initializing gradle... 1.0s Resolving dependencies... 16.2s Calling mockable JAR artifact transform to create file: C:\Users\zsl\.gradle\caches\transforms-1\files-1.1\android.jar\6f5327df033192a3e0966171fe7db8d8\android.jar with input D:\android\android\platforms\android-28\android.jar Running Gradle task 'assembleRelease'... Running Gradle task 'assembleRelease'... Done 66.0s Built build\app\outputs\apk\release\app-release.apk (10.4MB).
我们可以看到生成的apk存放在build\app\outputs\apk\release\app-release.apk
执行flutter install将安装到连接的设备上,如果之前有Debug版本已经安装到手机上,需要将之前版本卸载才能安装成功。
以上就是一个Android App从创建到打包安装的全过程。
三、常见问题
-
Error running Gradle 错误
这个错误是在重装环境后出现的,重装并创建第一个项目后flutter run的时候爆出了这个错,* Error running Gradle
ProcessException: Process "xxx/first_flutter_app/android/gradlew" exited abnormally: Project evaluation failed including an error in afterEvaluate {}. Run with --stacktrace for details of the afterEvaluate {} error. FAILURE: Build failed with an exception. * Where: Build file 'xxx/first_flutter_app/android/app/build.gradle' line: 25 * What went wrong: A problem occurred evaluating project ':app'. > Could not resolve all files for configuration 'classpath'. > Could not find lint-gradle-api.jar (com.android.tools.lint:lint-gradle-api:26.1.2). Searched in the following locations: https://jcenter.bintray.com/com/android/tools/lint/lint-gradle-api/26.1.2/lint-gradle-api-26.1.2.jar * 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 0s Command: xxx/first_flutter_app/android/gradlew app:properties Finished with error: Please review your Gradle project setup in the android/ folder.
从这里面当时并没看出来是什么问题,但可以确定gradle出的问题,后来网上查了下发现是下载文件时候需要*,否则有些文件就下载不了出现了这个问题。
解决办法有两个-
第一个是*这肯定是不方便的。
-
第二个解决办法就是使用阿里云的镜像文件。
下面介绍第二种解决办法,首先找到Android中的gradle文件,将代码改为下面格式
buildscript { repositories { // google() // jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } dependencies { classpath 'com.android.tools.build:gradle:3.2.1' } } allprojects { repositories { // google() // jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } }
第二步就是修改flutter sdk中的flutter.gradle文件,具体路径为fluttersdk目录▸ packages ▸ flutter_tools ▸ gradle 这个文件的修改有两种类型
第一种:repositories{ google() gcenter() }
这种就按下面方式修改
repositories{ //google() //gcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url'http://maven.aliyun.com/nexus/content/groups/public'} }
还有一种情况
repositories { jcenter() maven { url 'https://dl.google.com/dl/android/maven2' }
这种就按下面方式修改
repositories { //jcenter() // maven { // url 'https://dl.google.com/dl/android/maven2' // } maven{ url 'https://maven.aliyun.com/repository/jcenter' } maven{ url 'http://maven.aliyun.com/nexus/content/groups/public' } }
这样就可以解决这个问题了
-
-
无法链接文件
换电脑重装flutter环境后运行之前项目出现下面错误
--auto-add-overlay\ --non-final-ids\ -0\ apk\ --no-version-vectors Daemon: AAPT2 aapt2-3.2.1-4818971-windows Daemon #0 * 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 6s Running Gradle task 'assembleRelease'... Running Gradle task 'assembleRelease'... Done 9.0s ******************************************************************************************* The Gradle failure may have been because of AndroidX incompatibilities in this Flutter app. See https://goo.gl/CP92wY for more information on the problem and how to fix it. ******************************************************************************************* Gradle task assembleRelease failed with exit code 1
这个错费了很大的功夫,因为下面爆出了可能是androidX问题所以解决问题的思路就一直被带偏了,一直想着解决androidX的问题,但是这个问题以前已经解决了为什么还会出现。之后想着更换极光版本,就将版本切换到了0.0.13,还是不行,就有将版本切换回了0.0.11,但是get package之后发现.package中连接的地址还是0.0.13并不是0.0.11,然后就去github上查找,发现好像没有0.0.11这个版本了,就将之前的0.0.11库复制过来,成功解决。
类似问题需要我们查看.packages文件中引入的依赖库版本是否与yaml文件中的依赖库版本相同,不过git无法下载指定的库可以到github上将指定的依赖下载下来,解压到fluttersdk/.pub-cache/hosted/pub.flutter-io.cn下。
-
Androidx兼容性问题
Execution failed for task ‘:app:preDebugBuild’.
Android dependency ‘androidx.core:core’ has different version for the compile (1.0.0) and runtime (1.0.1) classpath. You should manually set the same version via DependencyResolution
Android代码使用Android.support库来确保向后兼容性老版本。目前support库已经停止维护,并替换为AndroidX,AndroidX具有与旧库想通过的功能和一些附加功能,但这两套库是不兼容的,所以会报错。未来都会为AndroidX为主,Android Support Library已经不再建议使用,并会慢慢停止维护。另外,从Android Studio 3.4.2开始,新建的项目已经强制勾选使用AndroidX架构了。
Launching lib/main.dart on Redmi Note 7 Pro in debug mode... Initializing gradle... Resolving dependencies... Running Gradle task 'assembleDebug'... FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:preDebugBuild'. > Android dependency 'androidx.core:core' has different version for the compile (1.0.0) and runtime (1.0.1) classpath. You should manually set the same version via DependencyResolution * 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 6s Finished with error: Gradle task assembleDebug failed with exit code 1
解决办法
目前网上主要有两种解决办法,第一种就是规避使用AndroidX的插件,避免使用AndroidX,显然这将做出很大的妥协,绝对不是最好的方式。另一种就是集成AndroidX,这种方式其实也不简单,我第一次通过AS去做的时候就不知道为什么没有成功,手动的话又很麻烦,还容易出错,这也许不太适合较大的老项目。
针对我的问题我找到了解决办法,在项目级build.gradle文件中增加下面的代码块便能解决问题subprojects { project.configurations.all { resolutionStrategy.eachDependency { details -> if (details.requested.group == 'com.android.support' && !details.requested.name.contains('multidex') ) { details.useVersion "27.1.1" } if (details.requested.group == 'androidx.core' && !details.requested.name.contains('androidx') ) { details.useVersion "1.0.1" } } } } }
完整的build.gradle代码
buildscript { ext.kotlin_version = '1.3.0' repositories { // google() // jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } google() } dependencies { classpath 'com.android.tools.build:gradle:3.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } subprojects { project.configurations.all { resolutionStrategy.eachDependency { details -> if (details.requested.group == 'com.android.support' && !details.requested.name.contains('multidex') ) { details.useVersion "27.1.1" } if (details.requested.group == 'androidx.core' && !details.requested.name.contains('androidx') ) { details.useVersion "1.0.2" } if (details.requested.group == 'androidx.appcompat' && !details.requested.name.contains('androidx') ) { details.useVersion "1.0.2" } } } } } allprojects { repositories { // google() // jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } } rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { project.evaluationDependsOn(':app') } task clean(type: Delete) { delete rootProject.buildDir } } } } allprojects { repositories { // google() // jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } } rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { project.evaluationDependsOn(':app') } task clean(type: Delete) { delete rootProject.buildDir }
上一篇: 女性经期吃什么?缓解不适试试4款糖水
下一篇: 夏季瘦身季 吃这瘦身汤瘦到没朋友
推荐阅读
-
使用vue-cli创建项目的图文教程(新手入门篇)
-
ubuntu18.04 -- 创建第一个Django项目
-
JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识
-
第一个,net core项目,一起入门 !!!
-
Electron – 基础学习(1): 环境安装、创建项目及入门
-
01(Windows系统) Flutter 开发环境搭建 -flutter系列项目教程
-
idea创建一个入门Spring Boot项目(controller层)使用Moven代码管理
-
iOS项目中混编flutter和打包发布
-
用Eclipse搭建Android开发环境并创建第一个Android项目(eclipse+android sdk)
-
iOS项目中集成Flutter的最新适配升级