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

前言

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

一轉(zhuǎn)眼 Flutter 1.2 都已經(jīng)發(fā)布了,這下實在是坐不住了。特地花了一周的時間來做了 一文 這個 APP 。以此來簡單了解下這款全新跨平臺框架的魅力。

image

第一個 APP

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

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

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

別擔心,這是正?,F(xiàn)象,對我們這種只想初步體驗的用戶來說,沒有系統(tǒng)的學習,這種情況才是正?,F(xiàn)象。

保持開放的心態(tài),多學多看。碰到不懂的,多查,碰到不知道怎么寫的,多看官方的源碼實現(xiàn),等代碼量上去了,自然就熟練了。

第二個 APP

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

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

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

一文

由于項目一周的時間限制,本次就要求項目盡可能的簡單,頁面盡可能的少。且,要盡可能的完成多的功能點,于是 一文 就誕生了。

一文 是基于每日一文 API 開發(fā)的一款全新的 Flutter APP。

下載

https://github.com/chengww5217/one_article/releases

截圖

image
image
image
image

Highlights

  • 這個項目足夠簡單
    • 只有 splash、home、starred list 三個界面
  • 這個項目功能點足夠多
    • splah 頁面創(chuàng)建,去除啟動白屏
    • 聯(lián)網(wǎng)、Json 解析、文章展示
    • 數(shù)據(jù)庫保存文章
    • 主題切換,字體調(diào)整,配置本地保存(SP)
    • 國際化
    • ···
  • 這個項目還是有用的
    • 和一般純練手 Demo 不同,每日一文是我每天都會看的

開始項目

注意:在源代碼中,一個頁面可能包含多個功能實現(xiàn),在實際做的時候,請依據(jù) APP 預覽一項一項進行實現(xiàn)。

源代碼并不是標準答案,有問題歡迎提交 PR 進行貢獻。

API

API 來源:https://github.com/jokermonn/-Api/blob/master/OneArticle.md

分析 API 進行聯(lián)網(wǎng)實現(xiàn),主要要求實現(xiàn)聯(lián)網(wǎng)獲取文章,獲取后進行 Json 解析到 bean,然后進行簡單的錯誤 handle。

參考文章:

Splash Page

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

第一個頁面,主要要求掌握頁面編寫的常規(guī)套路以及 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,),
      );
    });
  }
}

生命周期如下:

image

圖片轉(zhuǎn)載自https://segmentfault.com/a/1190000015211309

具體 Splash 頁面講解參考我的博客:Flutter 開發(fā) Android & IOS 啟動頁 splash page

Home Page

主頁面主要是對文章進行展示以及相關(guān)設置項。

image

點擊左上角可以彈出相關(guān)配置彈窗。

考慮到布局的復雜度,這里可以將底部彈窗抽離出單獨寫進一個 .dart 文件。

從這部分就涉及到各個控件的使用和狀態(tài)設置,點擊事件等內(nèi)容。

這部分基本就是程序的核心內(nèi)容了。


完成了該部分之后就是對程序進行優(yōu)化,添加數(shù)據(jù)庫來緩存數(shù)據(jù),日期判斷切換,文章收藏等。

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

雜項

最后就是國際化,添加資源和打包等一些雜項了,具體參見

https://flutter.dev/docs/development/accessibility-and-localization/internationalization

https://flutter.dev/docs/deployment/android

結(jié)語

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

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

在初步使用 Flutter 之后,我發(fā)覺似乎 Flutter 短時間內(nèi)并不能讓我不學習原生開發(fā)就直接使用 Flutter 解決移動客戶端開發(fā)。

在不斷的使(zhe)用(teng)過程中,發(fā)現(xiàn)碰到好多問題還是需要你必須用原生開發(fā)的知識去解決相應的問題。 比如項目里面獲取已收藏文章,是這樣從數(shù)據(jù)庫里面獲取文件的:

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 的列。

但是實際運行的時候,發(fā)現(xiàn)在 Android 設備上面總是獲取不到。

Android 數(shù)據(jù)庫使用的是 Sqlite,不能存儲 bool(boolean)。相反,布爾值被存儲為整數(shù) 0(false)和 1(true)。

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

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

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


本文到這里就要結(jié)束了,不怎么涉及具體代碼,只是一周時間的 Flutter 簡單上手。如果大家對項目有興趣,歡迎大家 star、fork 以及提交 PR,謝謝大家。

項目地址:https://github.com/chengww5217/one_article

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容