Android Flutter搭建記錄

一、搭建Flutter環(huán)境

Flutter官網(wǎng): https://flutterchina.club/

windows環(huán)境搭建過程

  1. 由于在國內(nèi)訪問Flutter有時可能會受到限制循狰,為了能正常獲取Flutter SDK以及之后第一次執(zhí)行 flutter doctor 能夠正常完成,可以先添加鏡像地址鳄哭,F(xiàn)lutter官方為中國開發(fā)者搭建了臨時鏡像趁俊。

    環(huán)境變量加入到用戶環(huán)境變量中:

export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

或者:

1595225032715
1595225043271

2.下載Flutter SDK

如果下載慢無法下載可以使用git下載:

 git clone -b beta https:*//github.com/flutter/flutter.git

3.將安裝包zip解壓到你想安裝Flutter SDK的路徑 ,即為你的Flutter安裝目錄

4.在Flutter安裝目錄的flutter文件下找到flutter_console.bat糊探,雙擊運行并啟動flutter命令行

1594956092871

5.打開一個新的命令提示符或PowerShell窗口并運行以下命令以查看是否需要安裝任何依賴項來完成安裝:

運行 flutter doctor挎狸,第一次運行有點慢健提,需要點等待時間

flutter doctor: 下載它自己的依賴項并自行編譯

1594957325718

6.Android Studio安裝flutter插件,重啟

1594957469700
1594957513096

到此說明flutter環(huán)境已經(jīng)搭建完成

二伟叛、新建Flutter工程

如果首次創(chuàng)建項目如果一直卡在Creating Flutter project上,先打開項目文件脐嫂,如果里面已經(jīng)有了創(chuàng)建的文件统刮,那么從任務(wù)管理器關(guān)掉Android Studio,然后重新打開,點擊Open an existing Android Studio project,找到項目文件账千,打開就行了侥蒙。

1594957559893

工程的目錄結(jié)構(gòu):

1594967329016

官方文檔中:

在這個示例中,你將主要編輯Dart代碼所在的 lib/main.dart 文件,

我們可以修改main.dart文件來實現(xiàn)簡單的信息修改匀奏。

我們先運行看一下效果:

1594967413771

三鞭衩、熱重載

看一下main.dart文件

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.green,
        // This makes the visual density adapt to the platform that you run
        // the app on. For desktop platforms, the controls will be smaller and
        // closer together (more dense) than on mobile platforms.
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

注釋中提示我們可以改變

primarySwatch: Colors.green,來修改app的主題顏色,我們來試著修改顏色并體驗 熱重載

1594967682076

反應(yīng)很快娃善,日志顯示1122ms完成了熱重載论衍。

四、使用外部包(package)

我們參考官網(wǎng)提供的步驟聚磺,使用 english_words 開源軟件包

flutter一些開源的軟件包:https://pub.dev/flutter/packages

1.pubspec文件管理Flutter應(yīng)用程序的assets(資源坯台,如圖片、package等) 瘫寝,所以我們可以到 pubspec.yaml 添加package的依賴

1594968118124
  1. 單擊右上角的 Packages get蜒蕾,這會將依賴包安裝到您的項目稠炬。您可以在控制臺中看到以下內(nèi)容:
1594968242387
  1. lib/main.dart 中, 引入 english_words
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

4.使用詞庫

1594968486519

此時假如package,熱更新會報錯咪啡,所以需要先停止運行首启,在運行

之后每一次熱更新,MyHomePage的title都會隨機出現(xiàn)一個單詞撤摸。

以上主要是記錄軟件包package的使用

五毅桃、頁面跳轉(zhuǎn)

Flutter的路由和導(dǎo)航功能 ,管理多個頁面時有兩個核心概念和類:RouteNavigator愁溜。 一個route是一個屏幕或頁面的抽象疾嗅,Navigator是管理route的Widget。Navigator可以通過route入棧和出棧來實現(xiàn)頁面之間的跳轉(zhuǎn)冕象。

1.簡單的頁面跳轉(zhuǎn)

我們先實現(xiàn)簡單的頁面跳轉(zhuǎn)代承,可以用 Navigator.push 和 Navigator.pop 實現(xiàn)

1.新建一個page,新建newpage.dart文件渐扮,繼承StatelessWidget论悴,可以看到需要復(fù)寫createState

如果不復(fù)寫,那么只能抽象墓律,或者noSuchMethod膀估,一會能跳轉(zhuǎn)了我們可以驗證一下noSuchMethod是什么意思。

1594969991861

在頁面顯示一串Text耻讽,并定義onPressed動作的事件察纯,使用pop返回到上一頁

   @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text('New page'),),
      body: Center(child: RaisedButton(
          child: Text('點擊返回上一頁'),
          onPressed: () {
            Navigator.pop(context);
          }),),);
  }

2.main.dart找到懸浮按鈕的點擊事件,刪除setState针肥,添加跳轉(zhuǎn)動作

  void _incrementCounter() {
     Navigator.push(context,
        MaterialPageRoute(builder: (context) => Newpage()));
  }

3.熱重載饼记,查看并點擊懸浮按鈕,跳轉(zhuǎn)到了第二個頁面慰枕,點擊可以返回到上一頁

1595212566594

2.通過routes路徑方式跳轉(zhuǎn)

創(chuàng)建 MaterialApp 時可以指定 routes 參數(shù)具则,該參數(shù)是一個映射路由名稱和構(gòu)造器的 Map。

 return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.green,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      routes: {
        "home": (context) => MyHomePage(),
        "newpage": (context) => Newpage()
      },
      home: MyHomePage(title: wordPair.asPascalCase),
    );

跳轉(zhuǎn)直接使用Navigator.pushNamed(context, "newpage");

Navigator.pushNamed(context, "newpage");

3.傳遞數(shù)據(jù)到下一個頁面

傳遞的方式有兩種:

  • 在構(gòu)造方法中傳遞數(shù)據(jù)
  • 在Route中傳遞數(shù)據(jù)給下一個頁面

分別來使用一下兩種方式

第一種:在跳轉(zhuǎn)的時候?qū)?shù)傳入具帮,在接受頁面使用ModalRoute.of(context).settings.arguments獲取

class User {
  String name;
  int age;

  String toString(){
    return ("name:" + this.name + " age:" + this.age.toString());
  }
  User({this.name, this.age});
}



void startNewPage() {
//     Navigator.push(context,
//        MaterialPageRoute(builder: (context) => Newpage()));

//     Navigator.pushNamed(context, "newpage");
  
     Navigator.pushNamed(context, "newpage", arguments: User(name: "GodV",age: 23));
     
  }

接受數(shù)據(jù)博肋, ModalRoute.of(context).settings.arguments;方式獲取傳遞的數(shù)據(jù)

@override
  Widget build(BuildContext context) {
    //構(gòu)造獲取傳遞過來的參數(shù)user
    final User user = ModalRoute.of(context).settings.arguments;
    return Scaffold(appBar: AppBar(title: Text("第二頁"),),
      body: Center(child: RaisedButton(
          child: Text('傳遞的參數(shù):' + user.toString()),
          onPressed: () {
            Navigator.pop(context);
          }),),);
  }

第二種: onGenerateRoute定義了返回的目標頁面需要帶有參數(shù),另外目標頁面寫構(gòu)造參數(shù)

 return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.green,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      routes: {
        "home": (context) => MyHomePage(),
      },
      onGenerateRoute: (settings) {
        if (settings.name == "newpage") {
          final User args = settings.arguments;
          return MaterialPageRoute(builder: (context) {
            return Newpage(
              user: args,
            );
          });
        }
      },
      home: MyHomePage(title: wordPair.asPascalCase),
    );

發(fā)送數(shù)據(jù)的方法沒有改變:

 Navigator.pushNamed(context, "newpage", arguments: User(name: "Zgg01",age: 23));

接受頁面:

  final User user;
  Newpage({this.user});
  
  @override
  Widget build(BuildContext context) {
    //構(gòu)造獲取傳遞過來的參數(shù)user
    return Scaffold(appBar: AppBar(title: Text("第二頁"),),
      body: Center(child: RaisedButton(
          child: Text('傳遞的參數(shù):' + user.toString()),
          onPressed: () {
            Navigator.pop(context);
          }),),);
  }

4.接收頁面返回值

定義接受值顯示在Text上

   String reciveString = "接受的值:";
  
  children: <Widget>[
            Text(
              '路由跳轉(zhuǎn)',
            ),
            Text(
              '$reciveString',
//              style: Theme.of(context).textTheme.headline4,
            ),
          ],

打開頁面時使用then接受返回回來的參數(shù)蜂厅,需要使用setState來更新組件的值

         Navigator.pushNamed(context, "newpage", arguments: User(name: "Zgg01",age: 23))
              .then((value) => {
                 setState(() {
                   reciveString = value.toString();
                  })
               });

在第二個頁面發(fā)送需要返回的值

  @override
  Widget build(BuildContext context) {
    //構(gòu)造獲取傳遞過來的參數(shù)user
    return Scaffold(appBar: AppBar(title: Text("第二頁"),),
      body: Center(child: RaisedButton(
          child: Text('傳遞的參數(shù):' + user.toString()),
          onPressed: () {
            Navigator.pop(context, User(name: "Forever",age: 20));
          }),),);
  }

第二個頁面點擊返回后效果:

1595229311210

六匪凡、添加一個 有狀態(tài)的部件(Stateful widget)

部件 分為狀態(tài)可變的和狀態(tài)不可變的

Stateless widgets 是不可變的, 這意味著它們的屬性不能改變 - 所有的值都是最終的.

Stateful widgets 持有的狀態(tài)可能在widget生命周期中發(fā)生變化. 實現(xiàn)一個 stateful widget 至少需要兩個類:

  1. 一個 StatefulWidget類。
  2. 一個 State類掘猿。 StatefulWidget類本身是不變的锹雏,但是 State類在widget生命周期中始終存在.

以官網(wǎng)的添加一個ListView為例

第一步:定義一個Page繼承StatefulWidget

class ListPage extends StatefulWidget {
  final String title;
  ListPage({Key key, this.title}) : super(key: key);
  @override
  State<StatefulWidget> createState() {
     return ListWordsState();
  }
}

第二步:定義ListView頁面,定義ListWordsState繼承State<ListPage>

class ListWordsState extends State<ListPage>{
  final _suggestions = <WordPair>[];
  final _biggerFont = const TextStyle(fontSize: 18.0);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("ListView"),),
      body: new ListView.builder(
          padding: const EdgeInsets.all(16.0),
          // 對于每個建議的單詞對都會調(diào)用一次itemBuilder术奖,然后將單詞對添加到ListTile行中
          // 在偶數(shù)行礁遵,該函數(shù)會為單詞對添加一個ListTile row.
          // 在奇數(shù)行轻绞,該函數(shù)會添加一個分割線widget,來分隔相鄰的詞對佣耐。
          // 注意政勃,在小屏幕上,分割線看起來可能比較吃力兼砖。
          itemBuilder: (context, i) {
            // 在每一列之前奸远,添加一個1像素高的分隔線widget
            if (i.isOdd) return new Divider();

            // 語法 "i ~/ 2" 表示i除以2,但返回值是整形(向下取整)讽挟,比如i為:1, 2, 3, 4, 5
            // 時懒叛,結(jié)果為0, 1, 1, 2, 2, 這可以計算出ListView中減去分隔線后的實際單詞對數(shù)量
            final index = i ~/ 2;
            // 如果是建議列表中最后一個單詞對
            if (index >= _suggestions.length) {
              // ...接著再生成10個單詞對耽梅,然后添加到建議列表
              _suggestions.addAll(generateWordPairs().take(10));
            }
            return _buildRow(_suggestions[index]);
          }
       ),
    );
  }

  //生成每一個Item的TextView
  Widget _buildRow(WordPair pair) {
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
    );
  }

}

注意:復(fù)寫Widget build(BuildContext context)時薛窥,需要return一個以Scaffold為根布局的組件,之后再body里面定義ListView

padding:即對應(yīng)Android的padding眼姐,可以使用all修改全部的內(nèi)邊距诅迷,或者使用fromLTRB定義每一個方向的內(nèi)邊距


  const EdgeInsets.all(double value)
    : left = value,
      top = value,
      right = value,
      bottom = value;
      
      
const EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom);

itemBuilder: (context, i):生成item時的遍歷

_buildRow:定義每一個Item的內(nèi)容

第三步:添加交互

點擊收藏,顯示收藏圖標

1.添加一個 _saved Set(集合) 到RandomWordsState

class ListWordsState extends State<ListPage>{
  final _suggestions = <WordPair>[];
  final _biggerFont = const TextStyle(fontSize: 18.0);
  //添加一個 _saved Set(集合) 到RandomWordsState
  final _saved = new Set<WordPair>();
 }
  1. _buildRow 方法中添加 alreadySaved來檢查確保單詞對還沒有添加到收藏夾中众旗。
  2. 定義trailing: new Icon圖標罢杉,通過alreadySaved狀態(tài)來設(shè)置顏色
  3. 定義onTap方法,更新對應(yīng)item的收藏狀態(tài)
Widget _buildRow(WordPair pair) {
    final alreadySaved = _saved.contains(pair);

    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: new Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }

效果:

1595237316272

關(guān)于Flutter和Android對應(yīng)的Api可以參考: https://flutterchina.club/flutter-for-android/#flutter%E5%92%8Candroid%E4%B8%AD%E7%9A%84view

以上Demo GitHub地址: https://github.com/heezier/Flutter

參考:

Flutter中文官網(wǎng)

Flutter + Tensorflow Lite環(huán)境配置

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贡歧,一起剝皮案震驚了整個濱河市滩租,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌利朵,老刑警劉巖持际,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哗咆,居然都是意外死亡,警方通過查閱死者的電腦和手機益眉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門晌柬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人郭脂,你說我怎么就攤上這事年碘。” “怎么了展鸡?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵屿衅,是天一觀的道長。 經(jīng)常有香客問我莹弊,道長涤久,這世上最難降的妖魔是什么涡尘? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮响迂,結(jié)果婚禮上考抄,老公的妹妹穿的比我還像新娘。我一直安慰自己蔗彤,他們只是感情好川梅,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著然遏,像睡著了一般贫途。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上待侵,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天丢早,我揣著相機與錄音,去河邊找鬼诫给。 笑死香拉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的中狂。 我是一名探鬼主播凫碌,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胃榕!你這毒婦竟也來了盛险?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤勋又,失蹤者是張志新(化名)和其女友劉穎苦掘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楔壤,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡鹤啡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蹲嚣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片递瑰。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖隙畜,靈堂內(nèi)的尸體忽然破棺而出抖部,到底是詐尸還是另有隱情,我是刑警寧澤议惰,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布慎颗,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏俯萎。R本人自食惡果不足惜傲宜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望讯屈。 院中可真熱鬧蛋哭,春花似錦、人聲如沸涮母。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叛本。三九已至沪蓬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間来候,已是汗流浹背跷叉。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留营搅,地道東北人云挟。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像转质,于是被迫代替她去往敵國和親园欣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353