自學Flutter

137 回覆
70 Like 2 Dislike
2022-06-15 17:24:58
最近開始學flutter 想試下寫一個app
見到軟件台有好多巴打開實戰post 所以自己都想開一個分享同記錄低 如果你有寫開flutter 歡迎分享同俾意見交流

如果你都想學flutter 可以參考以下link
https://docs.flutter.dev/get-started/install
https://github.com/Tomic-Riedel/Flutter-Roadmap
https://github.com/olexale/flutter_roadmap



同埋可以去flutter youtube channel睇以下playlist
每條片都係1, 2分鐘 介紹widget同package 好快pick up

https://www.youtube.com/playlist?list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG
https://www.youtube.com/playlist?list=PLjxrf2q8roU1quF6ny8oFHJ2gBdrYN_AK

以下係兩個app可以好快show case widget點用
https://github.com/flutter/gallery
https://github.com/X-Wei/flutter_catalog

package可以去呢度搵
https://pub.dev/

dartpad可以俾你响browser試嘢
https://dartpad.dev/

另外 可以睇睇以下blog 介紹lint rules settings
default有好多rules都冇enable 你可以揀個適合你嘅
https://rydmike.com/blog_flutter_linting.html

今次想寫一個app 經api拎data同做local cache
呢度有好多API揀
https://github.com/public-apis/public-apis

我就揀咗
https://pokeapi.co/

暫時會嘗試
經rest api拎data 同用local database cache data
support light/dark mode
加animation
用riverpod 做state management
類似咁樣



因為整理需時 更新可能會好慢
打住咁多先
2022-06-15 17:46:22
無IT底,都想自學Flutter,
想問係咪同寫網站一樣,要寫好左個UI先再寫d功能?
2022-06-15 20:50:01
flutter入面UI同logic都係用dart寫
你可以寫咗個login page UI先
再寫login功能

又或者由domain layer開始寫都得

初學可以試下寫啲簡單嘢先
BMI calculator
weather app等等
2022-06-15 21:15:14
一齊學下Flutter
讀完CS都冇用過
2022-06-15 21:49:41
比心機
2022-06-15 22:48:55
一齊學
2022-06-15 22:49:36
多謝推post
2022-06-15 22:57:15
lm
2022-06-15 22:58:17
lm
2022-06-15 23:05:38
支持技術po
2022-06-15 23:08:37
Lm學野
2022-06-15 23:09:09
flutter post當然flutter好

冇用過react native 唔太清楚
但兩樣都有人用
你可以兩樣都試試
再揀一個
2022-06-15 23:14:22
點寫會員注冊登入個D
2022-06-15 23:35:17
寫開SwiftUI
前排轉玩flutter
想請教下flutter 寫web 點樣分幾個html 出嚟
而唔係一個index.html 搞掂曬?
2022-06-16 01:53:47
唔記得咗講 今次我會嘗試follow Uncle Bob clean architecture
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

主要分開3個layer
domain
data
ui

首先我揀咗由pokemon move開始 比較簡單
開始之前先去api 睇move有咩fields
https://pokeapi.co/docs/v2#moves-section

然後由domain layer開始define move entity 同repository
fields暫時都係用primitive types 有需要遲啲可以轉

class Move {
  const Move({
    required this.id,
    required this.name,
    required this.description,
    required this.power,
    required this.accuracy,
    required this.pp,
    required this.damageClass,
    required this.generation,
  });

  final int id;
  final String name;
  final String description;
  final int? power;
  final int? accuracy;
  final int? pp;
  final String damageClass;
  final String generation;
}


abstract class IMoveRepository {
  Future<List<Move>> fetchData({int limit = 20, int offset = 0});
}
2022-06-16 01:56:09
到data layer
poke api default 1次會拎20個result
但個result唔係直接俾data你 而係一條url俾你再去拎data
其實有啲煩
https://pokeapi.co/docs/v2#resource-listspagination-section

test api response 可以用postman試
以下係 https://pokeapi.co/api/v2/move/ 嘅response

{
    "count": 844,
    "next": "https://pokeapi.co/api/v2/move/?offset=20&limit=20",
    "previous": null,
    "results": [
        {
            "name": "pound",
            "url": "https://pokeapi.co/api/v2/move/1/"
        },
        {
            "name": "karate-chop",
            "url": "https://pokeapi.co/api/v2/move/2/"
        },
        ...
    ]
}


咁我哋就跟住個json format 去 define 1個class 同埋用 json_serializable 去handle deserialization
https://pub.dev/packages/json_serializable

part 'resource_lists.g.dart';

@JsonSerializable()
class NamedApiResourceList{
  const NamedApiResourceList({
    required this.count,
    required this.next,
    required this.previous,
    required this.results,
  });

  final int count;
  final String? next;
  final String? previous;
  final List<NamedApiResource> results;
  
  factory NamedApiResourceList.fromJson(Map<String, dynamic> json) {
    return _$NamedApiResourceListFromJson(json);
  }  
}
2022-06-16 01:59:07
同樣地 define move model 同其他需要嘅model

@JsonSerializable(explicitToJson: true, fieldRename: FieldRename.snake, createToJson: false)
class ApiMoveModel {
  const ApiMoveModel({
    required this.id,
    required this.name,
    required this.names,
    ...
  });

  final int id;
  final String name;
  final List<ApiNameModel> names;
  final int? power;
  final int? accuracy;
  final int? pp;
  final int priority;
  final List<ApiMoveFlavorTextModel> flavorTextEntries;
  final NamedApiResource damageClass;
  final NamedApiResource generation;

  factory ApiMoveModel.fromJson(Map<String, dynamic> json) {
    return _$ApiMoveModelFromJson(json);
  }
}


然後用retrofit去拎api data
https://pub.dev/packages/retrofit

@RestApi(baseUrl: 'https://pokeapi.co/api/v2/')
abstract class PokeApiClient {
  factory PokeApiClient(Dio dio, {String baseUrl}) = _PokeApiClient;

  @GET('/move')
  Future<HttpResponse<NamedApiResourceList>> getMovePage({
    @Query('limit') int limit = 20,
    @Query('offset') int offset = 0,
  });

  @GET('/move/{name}')
  Future<HttpResponse<ApiMoveModel>> getMove(@Path('name') String name);
}
2022-06-16 02:02:35
連登回覆係咪有字數限制
post多少少code就出error
2022-06-16 02:13:42
RemoteDataSource
首先拎page data
有20條url 再拎頭20個move data

而家我哋可以經poke api拎data, data type 由json => ApiMoveModel
但我哋要將data type由data layer轉去domain layer, 可以用extension去implement

最後我哋implement MoveRepository


UI layer
用riverpod 去做dependency injection 同state management


Move Page
响build method入面watch future provider會return AsyncValue<Move>
AsyncValuewhenmethod 俾你去handle唔同嘅state


Result

試埋error state
  Future<List<Move>> fetchData({int limit = 20, int offset = 0}) async {
    throw Exception('Can not reach Poke Api server');
    //final models = await _remoteDataSource.fetchMoves(limit: limit, offset: offset);
   // return models.map((model) => model.toEntity()).toList();
  }

2022-06-16 03:17:43
睇你用咩backend
你可以睇睇Firebase
2022-06-16 03:20:21
冇研究web development
等其他巴打答你
2022-06-16 03:23:35
做嘢寫緊Flutter 幾好玩
吹水台自選台熱 門最 新手機台時事台政事台World體育台娛樂台動漫台Apps台遊戲台影視台講故台健康台感情台家庭台潮流台美容台上班台財經台房屋台飲食台旅遊台學術台校園台汽車台音樂台創意台硬件台電器台攝影台玩具台寵物台軟件台活動台電訊台直播台站務台黑 洞