一週時間編寫你的第二個 Flutter APP

chengww發表於2019-04-21

前言

Flutter 從釋出之日起我就對其心心念唸了好久。 奈何這段時間實在是太忙了,加之自己拖延症時不時發作下,一直都抽不出時間來學習這個跨平臺框架。

一轉眼 Flutter 1.2 都已經發布了,這下實在是坐不住了。特地花了一週的時間來做了 一文 這個 APP 。以此來簡單瞭解下這款全新跨平臺框架的魅力。

一週時間編寫你的第二個 Flutter APP

第一個 APP

回到標題,既然是編寫第二個 Flutter APP,那就要求各位觀眾老爺自己對照著官方的 First Flutter APP 擼一遍。(中文連結:flutterchina.club/get-started…)

萬事開頭難,這部分包含了 dart 語言特性的學習,和 Flutter 框架一些特性的體驗。

如果你也是像我一樣只是花兩個小時簡單看了下 dart 語言的新特性就直接來擼第一個 APP。寫的時候可能會感覺總是在雲裡霧裡,很多地方都不明白。

別擔心,這是正常現象,對我們這種只想初步體驗的使用者來說,沒有系統的學習,這種情況才是正常現象。

保持開放的心態,多學多看。碰到不懂的,多查,碰到不知道怎麼寫的,多看官方的原始碼實現,等程式碼量上去了,自然就熟練了。

第二個 APP

照著官方示例完成了自己了的第一個 APP 編寫,是不是很有成就感?激動之餘,似乎感覺少了點什麼。

沒錯,畢竟只是照著官方的示例敲了一遍,說是 APP 也略簡陋了。是不是迫不及待的想做點什麼來鞏固下自己的學習呢。

這次就跟著我一起從專案的立項開始你的第二個 APP 吧。

一文

由於專案一週的時間限制,本次就要求專案儘可能的簡單,頁面儘可能的少。且,要儘可能的完成多的功能點,於是 一文 就誕生了。

一文 是基於每日一文 API 開發的一款全新的 Flutter APP。

下載

github.com/chengww5217…

截圖

一週時間編寫你的第二個 Flutter APP

一週時間編寫你的第二個 Flutter APP

一週時間編寫你的第二個 Flutter APP

一週時間編寫你的第二個 Flutter APP

Highlights

  • 這個專案足夠簡單
    • 只有 splash、home、starred list 三個介面
  • 這個專案功能點足夠多
    • splah 頁面建立,去除啟動白屏
    • 聯網、Json 解析、文章展示
    • 資料庫儲存文章
    • 主題切換,字型調整,配置本地儲存(SP)
    • 國際化
    • ···
  • 這個專案還是有用的
    • 和一般純練手 Demo 不同,每日一文是我每天都會看的

開始專案

注意:在原始碼中,一個頁面可能包含多個功能實現,在實際做的時候,請依據 APP 預覽一項一項進行實現。

原始碼並不是標準答案,有問題歡迎提交 PR 進行貢獻。

API

API 來源:github.com/jokermonn/-…

分析 API 進行聯網實現,主要要求實現聯網獲取文章,獲取後進行 Json 解析到 bean,然後進行簡單的錯誤 handle。

參考文章:

Splash Page

按照原生 APP 開發的套路,用於初始化以及展示廣告的 Splash 是必不可少的。

第一個頁面,主要要求掌握頁面編寫的常規套路以及 StatefulWidget 的生命週期等。

比如 class SplashPage 的寫法:

class SplashPage extends StatefulWidget {
  SplashPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  State<StatefulWidget> createState() {
    return _SplashPageState();
  }
}
複製程式碼

然後就是 class _SplashPageState 的編寫。

佈局就是一張圖片:

import 'package:flutter/material.dart';

class SplashPage extends StatefulWidget {
  SplashPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  State<StatefulWidget> createState() {
    return _SplashPageState();
  }
}

class _SplashPageState extends State<SplashPage> {
  
  @override
  void initState() {
    // TODO: do something to init
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Builder(builder: (context) {
      return Container(
        child: Image(image: AssetImage('assets/images/splash.png'), fit: BoxFit.fill,),
      );
    });
  }
}
複製程式碼

生命週期如下:

一週時間編寫你的第二個 Flutter APP

圖片轉載自segmentfault.com/a/119000001…

具體 Splash 頁面講解參考我的部落格:Flutter 開發 Android & IOS 啟動頁 splash page

Home Page

主頁面主要是對文章進行展示以及相關設定項。

一週時間編寫你的第二個 Flutter APP

點選左上角可以彈出相關配置彈窗。

考慮到佈局的複雜度,這裡可以將底部彈窗抽離出單獨寫進一個 .dart 檔案。

從這部分就涉及到各個控制元件的使用和狀態設定,點選事件等內容。

這部分基本就是程式的核心內容了。


完成了該部分之後就是對程式進行優化,新增資料庫來快取資料,日期判斷切換,文章收藏等。

這個部分是耗時最長的,也是從磕磕碰碰到逐漸熟練的過程。

雜項

最後就是國際化,新增資源和打包等一些雜項了,具體參見

flutter.dev/docs/develo…

flutter.dev/docs/deploy…

結語

從剛開始看 dart 語法,到這個專案開發完成。斷斷續續一共持續了三週的時間。每天抽出一到兩個小時,合計一共是 56 小時左右。減去畫 APP 圖示,啟動頁面圖片的兩個小時,勉強算得上八小時工作制的一週。

這一週的使用過程中,Flutter 有些特性讓人感覺相見恨晚:語法特性(型別動態檢查,支援 .? ?? 操作符)、簡單方便完備的 UI 方案、Hot Reload等。但是諸如複雜冗長的 view tree、資源的硬編碼、糟糕的 UI 控制元件 API 等又讓人頭痛不已。

在初步使用 Flutter 之後,我發覺似乎 Flutter 短時間內並不能讓我不學習原生開發就直接使用 Flutter 解決移動客戶端開發。

在不斷的使(zhe)用(teng)過程中,發現碰到好多問題還是需要你必須用原生開發的知識去解決相應的問題。 比如專案裡面獲取已收藏文章,是這樣從資料庫裡面獲取檔案的:

Future<List<ArticleBean>> getStarred() async {
    List<ArticleBean> articles = List();
    Database db = await getDB();
    List<Map<String, dynamic>> maps =
    await db.query(name, columns: [columnId, columnStarred, columnDate, columnData], where: "$columnStarred = ?", whereArgs: [true]);
    if (maps.length > 0) {
      for (Map<String, dynamic> map in maps) {
        ArticleBean article = ArticleBean.fromJson(map);
        articles.add(article);
      }
    }
    return articles;
  }
複製程式碼

請看核心查詢程式碼

await db.query(name, columns: [columnId, columnStarred, columnDate, columnData], where: "$columnStarred = ?", whereArgs: [true]);
複製程式碼

這裡就是獲取所有 starred 為 true 的列。

但是實際執行的時候,發現在 Android 裝置上面總是獲取不到。

Android 資料庫使用的是 Sqlite,不能儲存 bool(boolean)。相反,布林值被儲存為整數 0(false)和 1(true)。

故上述程式碼要改成下面的程式碼才生效。

await db.query(name, columns: [columnId, columnStarred, columnDate, columnData], where: "$columnStarred > ?", whereArgs: [0]);
複製程式碼

這只是一個很小的簡單例子,但是也說明了在 Flutter 上面並不能總是幫你解決原生的一些坑(這其實取決於各個框架的開發者為你做了多少相容處理)。


本文到這裡就要結束了,不怎麼涉及具體程式碼,只是一週時間的 Flutter 簡單上手。如果大家對專案有興趣,歡迎大家 star、fork 以及提交 PR,謝謝大家。

專案地址:github.com/chengww5217…

相關文章