Flutter — สร้าง Boilerplate Project ที่สมบูรณ์แบบตั้งแต่เริ่มต้น
![](https://post.nghiatu.com/assets/images/m/max/724/1*YUDS3243BpVSEDjQqwosvg.png)
เครดิต: Nguyễn Thành Minh (นักพัฒนา Android)
เราทุกคนเคยผ่านมาแล้ว — ที่ฉันหมายถึงคือเราทุกคนพยายามสร้างโครงการสำเร็จรูปสำหรับการทำงานหรือเป็นโครงการส่วนตัว โครงการสำเร็จรูปที่ดีจะช่วยเราประหยัดเวลาได้มากด้วยการแก้ปัญหาทั่วไป เช่น การเรียก API การประมวลผลข้อมูลจากฐานข้อมูล และบางทีที่สำคัญที่สุด — ทำให้โค้ดของเราเป็นระเบียบและสอดคล้องกัน เพื่อให้ผู้คนมีเวลาพยายามทำความเข้าใจโค้ดของเราได้ง่ายขึ้น ซีรีส์นี้มีวัตถุประสงค์เพื่อแบ่งปันโครงการสำเร็จรูปที่ฉันสร้าง ใช้ และบำรุงรักษาในช่วงสองปีที่ผ่านมา ไม่เพียงเท่านั้น ฉันจะแบ่งปันวิธีการเขียนโค้ด ตลอดจนวิธีแก้ไขปัญหาทั่วไปที่อาจเกิดขึ้น จากที่กล่าวมานี่คือตอนที่ 1: สำรวจโครงการ
ดูบน Github
![](https://post.nghiatu.com/assets/images/m/max/724/1*C2Euk2Dc9H3Pyf7I9WY3cw.png)
1. คุณสมบัติ
คุณสมบัติที่สร้างขึ้นในโครงการนี้:
- สถาปัตยกรรม: สถาปัตยกรรมที่สะอาด
- การจัดการสถานะ: flutter_bloc
- การนำทาง: auto_route
- DI: get_it ฉีดได้
- REST API: dio
- GraphQL: อาร์ทิมิส , graphql_flutter
- ฐานข้อมูล: objectbox
- ค่ากำหนดที่ใช้ร่วมกัน: encrypted_shared_preferences
- ชั้นข้อมูล: แช่แข็ง
- ผ้าสำลี: dart_code_metrics , flutter_lints
- CI/CD: Github Actions, Bitbucket Pipelines
- การทดสอบหน่วย: ม็อกเทล , bloc_test
- เพจ: infinite_scroll_pagination
- ยูทิลิตี้ : rxdart , dartx , async
- ตัว สร้างเนื้อหา: flutter_gen_runner , flutter_launcher_icons , flutter_native_splash
- คุณสมบัติอื่นๆ: คำขอ API ที่ล้มเหลวในการลองใหม่อัตโนมัติ, รีเฟรชโทเค็น,...
ในการรันโปรเจ็กต์นี้ตามที่ตั้งใจไว้ เวอร์ชั่น Flutter ของคุณต้องเป็น (ตรงเป๊ะ) 3.3.9 และMelos เวอร์ชั่น 2.8.0จะต้องติดตั้ง หากคุณต้องการมี Git Convention สำหรับทีมของคุณ คุณอาจติดตั้งlefthook ฉันจะพูดถึง Melos และ Lefthook ในตอนหลังของซีรีส์นี้ สำหรับตอนนี้ ต่อไปนี้เป็นวิธีการเรียกใช้โปรเจ็กต์
หมายเหตุ: ฉันใช้ VSCode และ macOS ดังนั้นฉันจึงไม่สามารถรับประกันได้ว่ามันจะทำงานบน Android Studio หรือ Windows ด้วย
2.1. การติดตั้งเมลอส
Clean Architecture ต้องการให้เราแบ่งโครงการออกเป็นหลายโมดูล (แพ็คเกจ) ซึ่งเป็นเหตุผลว่าทำไมเราจึงต้องการเครื่องมือสำหรับจัดการแพ็คเกจ — Melos ในการติดตั้ง Melos:
dart pub global activate melos 2.8.0
export PATH="$PATH:<path to flutter>/flutter/bin"
export PATH="$PATH:<path to flutter>/flutter/bin/cache/dart-sdk/bin"
export PATH="$PATH:~/.pub-cache/bin"
หลังจากติดตั้ง Melos แล้ว คุณจะต้องเรียกใช้คำสั่งmake gen_env
หรือdart run tools/gen_env.dart
. นี่เป็นเครื่องมือที่ฉันสร้างขึ้นเอง เพื่อสร้างenv
โฟลเดอร์เพื่อให้เราสามารถประกาศความลับ เช่น Google API_KEY, ข้อมูลรับรองความถูกต้องพื้นฐาน ฯลฯ เครื่องมือนี้จะอ่านค่าใน.env
ไฟล์ แล้วใส่ลงในdart-define
แฟล็กเมื่อแอพ Flutter วิ่งหรือสร้าง
![](https://post.nghiatu.com/assets/images/m/max/724/0*mDB5WDcrT8V1bfRT.png)
2.3. กำลังสร้างไฟล์
เมื่อเราได้env
โฟลเดอร์แล้ว เราก็แค่เรียกใช้คำmake sync
สั่ง นี่คือชวเลขสำหรับสามคำสั่ง:
melos bootstrap
melos run l10n
melos run force_build_all
ถัดไป คำสั่งmelos run l10n
ช่วยสร้างคลาสS
จาก.arb
ไฟล์ในresources
โมดูล
![](https://post.nghiatu.com/assets/images/m/max/724/0*_5CZPVpGGhnFCNnM.png)
สุดท้าย คำสั่งmelos run force_build_all
ช่วยสร้างไฟล์.g.dart
, .freezed.dart
ฯลฯ บนแพ็คเกจทั้งหมดที่มีbuild_runner
ไลบรารี
ตอนนี้เรียกmake run_dev
ใช้แอพและสนุกได้เลย!
3. สถาปัตยกรรมโครงการ
สรุปแล้วเรามี 6 โมดูล (แพ็คเกจ)
- แอป
- โดเมน
- ข้อมูล
- ทรัพยากร
- ใช้ร่วมกัน
- โปรแกรมเริ่มต้น
3.1. โมดูลแอพ
นี่คือที่ที่เราจะเขียนโค้ด UI และ Bloc นอกจากนี้ยังเป็นที่ที่เราจะจัดเก็บทรัพยากรของเรา เช่น สี มิติ และลักษณะข้อความ นี่คือที่ที่เราจะประกาศฟังก์ชัน main() ของเราเป็นจุดเริ่มต้นเพื่อให้แอปของเราทำงาน
![](https://post.nghiatu.com/assets/images/m/max/724/0*JK3J2lH4ZHOFjnUe.png)
ทั้งสองโฟลเดอร์app_icon
และsplash
มีไฟล์ เรา app-icon.yaml
จึงsplash.yaml
สามารถกำหนดค่าไอคอนแอปและหน้าจอสแปลชได้ตามคำแนะนำของไลบรารีflutter_launcher_iconsและflutter_native_splash
app
โฟลเดอร์ประกอบด้วยซึ่งAppBloc
เป็น Bloc ที่จัดเตรียมไว้ในMaterialApp
ที่ซึ่งหน้าจอทั้งหมดในแอปสามารถดึงข้อมูลออกมาได้ หรืออีกนัยหนึ่งคือ มันเหมือนกับ Bloc ที่แบ่งปันไปยังทุกหน้าจอ คุณสามารถใช้AppBloc
สำหรับงานที่ต้องอัปเดต UI ของหน้าจอทั้งหมด เช่น การตั้งค่าภาษา การสลับโหมดมืด/โหมดสว่าง
โฟลเดอร์คือ ที่ ที่เราจะเขียนโค้ดคลาส พื้นฐานbase
เช่นBasePageState
, BaseBloc
, BaseEvent
และBaseState
โฟลเดอร์shared_view
นี้เป็นที่ที่ฉันจะเขียนโค้ด UI ที่ใช้ร่วมกันในหลายหน้าจอ จากนั้นจึงจะนำไปใช้กับโปรเจ็กต์อื่นๆ ได้ ตัวอย่างเช่น: app_text_field
เป็นcircle_image
มุมมองกลุ่มทั่วไปที่เห็นในหน้าจอเข้าสู่ระบบและลงทะเบียน
โฟลเดอร์common_view
นี้เป็นที่ที่ฉันจะเขียนโค้ด UI ที่ใช้ร่วมกันในหลายหน้าจอ จากนั้นจึงจะนำไปใช้กับโปรเจ็กต์อื่นๆ ได้ ตัวอย่างเช่น , common_dialog
, common_app_bar
สามารถcommon_scaffold
ใช้ซ้ำได้ในหลายโปรเจ็กต์ แม้ว่าเราอาจต้องการปรับแต่งเล็กน้อยเพื่อให้ตรงกับสไตล์
โฟลเดอร์config
คือที่ที่ฉันจะเรียกใช้ฟังก์ชันการกำหนดค่าสำหรับโมดูลแอป เช่นFirebase.initializeApp()
โฟลเดอร์di
นี้มีไว้สำหรับการตั้งค่า DI สำหรับโมดูลแอป
โฟลเดอร์exception_handler
จะดูแลข้อยกเว้นทั้งหมดในโครงการ
โฟลเดอร์helper
มีคลาส Helper ที่ใช้สำหรับโมดูลแอปโดยเฉพาะ
โฟลเดอร์navigation
คือที่ที่เราจะประกาศหน้าจอตลอดจนกล่องโต้ตอบและแผ่นงานด้านล่างที่ใช้ในแอป
โฟลเดอร์resource
คือที่ที่เราจะประกาศทรัพยากรสำหรับ UI เช่น สี มิติ และลักษณะข้อความ
โฟลเดอร์ui
คือที่ที่ฉันจะเขียนโค้ด UI และ Bloc สำหรับแต่ละหน้าจอ
โฟลเดอร์utils
นี้เป็นที่ที่ฉันจะเขียนโค้ดฟังก์ชัน utils ที่ใช้สำหรับโมดูลแอปโดยเฉพาะ
3.2. โมดูลโดเมน
![](https://post.nghiatu.com/assets/images/m/max/724/0*o_GEFP48gP_B5NrF.png)
เช่นเดียวกับโมดูลแอป โฟลเดอร์config
และdi
ให้บริการตามวัตถุประสงค์ที่คล้ายกันในโมดูลโดเมน
โฟลเดอร์entity
ประกอบด้วยคลาสเอนทิตี เช่น ผู้ใช้และการจอง
โฟลเดอร์navigation
มีAppNavigator
คลาสซึ่งรับผิดชอบpush
, replace
, และpop
หน้าจอ
โฟลเดอร์repository
คือตำแหน่งที่เราจะประกาศคลาส Abstract Repository ในโครงการ
โฟลเดอร์usecase
คือที่ที่เราจะประกาศ Use Cases ในโครงการ
3.3. โมดูลข้อมูล
![](https://post.nghiatu.com/assets/images/m/max/724/0*Z0lGmJUzOVuIJ3tG.png)
ในทำนองเดียวกันโฟลเดอร์config
และdi
ให้บริการเพื่อจุดประสงค์เดียวกันที่นี่
โฟลเดอร์graphql
ประกอบด้วย.graphql
และschema.graphql
ถ้าโครงการของคุณใช้ GraphQL ไฟล์build.yaml
นี้ใช้สำหรับกำหนดค่าไฟล์ที่สร้างขึ้นซึ่งเกี่ยวข้องกับ GraphQL
โฟลเดอร์repository
มีคลาส Repository Implementation นอกจากนี้ยังมีหลายโฟลเดอร์:
converter
: สำหรับคลาสตัวแปลงการเข้ารหัสmapper
: สำหรับการเข้ารหัสคลาส Mapper ซึ่งจะใช้ในการแมปแบบจำลองข้อมูลเข้ากับเอนทิตีmodel
: สำหรับคลาสโมเดลข้อมูลการเข้ารหัสsource
: สำหรับการเข้ารหัสคลาสพื้นฐานเช่น RestApiClient, GraphQlApiClient รวมถึงการจัดหาแหล่งข้อมูลในโครงการเช่น AppApiService, AppDatabase, AppSharedPreferences, LocationDataSource
![](https://post.nghiatu.com/assets/images/m/max/724/0*MyhTTrXCJdXRuECS.png)
นี่เป็นโมดูลที่เรียบง่าย มีเฉพาะ.arb
ไฟล์ที่มีสตริงสำหรับการแปลเป็นภาษาท้องถิ่น โมดูลนี้แทรกเข้าไปในโมดูลอื่นอีกสองโมดูลapp
ดังนั้นdomain
คลาส UI, Bloc, Entity และ Use Case จึงสามารถใช้ได้
3.5. โมดูลที่ใช้ร่วมกัน
![](https://post.nghiatu.com/assets/images/m/max/724/0*32cREtsUmyNrjEaX.png)
ตามชื่อที่แนะนำ โมดูลนี้จัดเตรียมค่าคงที่ คลาสข้อยกเว้นที่กำหนดเอง คลาสตัวช่วย มิกซ์อิน และฟังก์ชัน utils สำหรับโมดูลอื่นๆ ที่จะใช้
3.6. โมดูล Initializer
![](https://post.nghiatu.com/assets/images/m/max/724/0*qDPnxRYXu_Wby34c.png)
โมดูลนี้มีเฉพาะคลาส AppInitializer คลาสนี้รับผิดชอบในการรวบรวมการกำหนดค่าทั้งหมดจากโมดูลอื่นในinit()
ฟังก์ชัน ฟังก์ชันmain()
จะต้องเรียกใช้init()
ฟังก์ชันนี้เพื่อดึงการกำหนดค่าทั้งหมดจากโมดูลทั้งหมดเท่านั้น
3.7. โฟลเดอร์และไฟล์อื่นๆ
โฟลเดอร์.github
นี้มีไว้สำหรับกำหนดค่า CI/CD หากโปรเจ็กต์ของคุณใช้ Github Actions
โฟลเดอร์.lefthook
และไฟล์lefthook.yml
มีไว้สำหรับกำหนดค่าแบบแผน Git โดยใช้ไลบรารีของ lefthook
โฟลเดอร์.vscode
นี้มีไว้สำหรับประกาศการตั้งค่า VSCode ที่ใช้สำหรับโครงการนี้
โฟลเดอร์.env
มีไว้สำหรับประกาศความลับสำหรับแต่ละสภาพแวดล้อม
โฟลเดอร์tools
มีเครื่องมือที่ฉันสร้างขึ้น
ไฟล์analysis_options.yaml
นี้มีไว้สำหรับประกาศกฎ linter ของสองไลบรารีflutter_lintsและdart_code_metrics
ไฟล์bitbucket-pipelines.yml
นี้มีไว้สำหรับกำหนดค่า CI หากโครงการของคุณใช้ Bitbucket Pipelines
ไฟล์makefile
ติดตามคำสั่งทั้งหมดที่ใช้ในโครงการ ตัวอย่างเช่น คำสั่งmake format
ช่วยจัดรูปแบบรหัสทั้งหมดที่มี.dart
นามสกุลไฟล์ภายในโครงการ มีคำสั่งอื่นๆ อีกมากมายmake test
ที่เรียกใช้การทดสอบหน่วยในทุกโมดูล
ไฟล์melos.yaml
นี้ใช้สำหรับกำหนดค่า Melos
บทสรุป
ทำไมเราต้องสร้างโมดูลอื่นสำหรับการกำหนดค่าเริ่มต้น คลาสตัวทำแผนที่ เอนทิตี และกรณีการใช้งานคืออะไร ฉันจะพูดถึงสิ่งเหล่านี้ในส่วนที่สองของซีรี่ส์นี้ — Clean Architecture