(Flutter) 釣魚資訊平台 - Day1 - 定位

更新於 2022/08/11閱讀時間約 10 分鐘
因為自己最近迷上了釣魚,但卻常常苦於不知道該去哪裡釣魚才能安全又有魚,因此想做個讓大家可以分享自己釣點以及釣況的App,讓大家都能找到適合自己的地方釣魚!
最近有新開一個部落格是在介紹Flutter相關的文章,大家可以去看看~

專案架構

專案架構可以參考我上一篇文章,這個專案我也是使用這個架構搭配GetX作為管理套件。

Pub.dev

Pub.dev提供了許多專門給Dart和Flutter使用的套件,如果有要實作的功能,可以先到這裡尋找有沒有別人已經做好的套件可以使用,可以省下許多麻煩,如果你有做好的套件也可以上傳到這裡供大家使用!

基本設定

Dart會找到你專案中的main()這個方法作為整個程式的起點,因此只能有一個main function,在你創建好專案後就會有基本的設定,不需要特別去調整。
接下來我們針對我們的App,做一些基本的設定
void main() async {
  await Firebase.initializeApp(); -> 確保建立Firebase相關的實例
  runZonedGuarded(() async {
    runApp(MyApp()); -> 啟動 App
  }, (Object error, StackTrace stack) async {
    // 這邊是錯誤處理,防止沒有被catch到的error, app會直接crash
    // 可以做一個dialog來提醒user 或是在此紀錄錯誤log 方便之後修正
  });
}
  • getPages 為整個app所有的畫面路徑設定
  • initialRoute 為app 進入的第一個畫面的路徑
  • initialBinding 是開啟app時會初始化的GetX Binding
  • 將原本的 MaterialApp 改為 GetMaterialApp,這樣就可以使用GetX來管理路徑了
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Fish Info',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: Routes.splashRoute, -> 第一個畫面的路徑
      getPages: Routes.routes,
      localizationsDelegates: const [
        DefaultCupertinoLocalizations.delegate, -> 之後說明用處
      ],
      initialBinding: GlobalBinding(),
    );
  }
}

路徑設定

這裡就是設定所有畫面的地方,以後有要新增畫面記得要回來這邊新增路徑跟GetPage,記得一定要使用binding來註冊GetXController,否則在某些特定情況下GetXController不會被正常初始化及釋放!
class Routes {
  Routes._();
  static const splashRoute = '/splash';
  static const homeRoute = '/home';
  static final List<GetPage> routes = [
    GetPage(name: splashRoute, page: () => const SplashPage(), binding: SplashBinding()),
    GetPage(name: homeRoute, page: () => const HomePage(), binding: HomeBinding()),
  ];
}

如何連結GetX Controller

只需要繼承Bindings並覆寫dependecies,在裡面初始化你想要的GetXController即可,如果需要多個相同種類的controller,可以新增tag的參數並在使用時代入參數即可,之後有機會再做詳細的說明。
如果不想要你的controller在頁面被移除時也跟著被移除,像是我們的GlobalController,可以在初始化時代入permanent參數為true即可。
class GlobalBinding extends Bindings {
  @override
  void dependencies() {
    Get.put<GlobalController>(GlobalController(), permanent: true);
  }
}

啟動畫面

在這個畫面我們要獲取使用者的位置,因此需要獲取權限才能去定位使用者,我們使用Geolocator這個套件來幫忙,根據不同的平台會有不同的設定需要先設定,大家可以點進去照著做就可以了!
我們創建一個GeoHelper class,裡面用來放我們Geo相關的code,方便我們之後重複使用。
class GeoHelper {
  GeoHelper._();
  static Future<Position> determinePosition() async {
    ...
  }
}
獲得地點的程式碼在Geolocator內有範例,大家可以去參考!

畫面

目前畫面還是空空如也,等到之後背景決定好之後再加上去~
class SplashPage extends StatelessWidget {
  const SplashPage({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return const SizedBox();
  }
}

GetX Controller

我們會在這個class內處理所有的邏輯,late可以讓參數不用馬上賦予值,但是一定要確保他在被使用前被賦予值,否則程式會出現錯誤,目前沒有方法檢查變數是否已經被賦予值,因此在使用時要格外小心!
這邊我們會使用CameraPosition,需要先拿到Google Map的套件才會有這個model,可以先去安裝,我們在下個畫面會使用到。
可以直接在terminal到專案位置輸入 flutter pub add google_maps_flutter,就會自己安裝了,所有在pub.dev的套件都有這個功能,可以到每個套件的Installing內找到。
class SplashController extends GetxController {
  late CameraPosition initialCameraPosition;
  late bool isPermissionAllowed;
  @override
  void onInit() {
    GeoHelper.determinePosition().then((position) {
      // 成功得到使用者的位置資訊
      initialCameraPosition = CameraPosition(
        target: LatLng(position.latitude, position.longitude),
        zoom: Config.defaultCameraZoom,
      );
      isPermissionAllowed = true;
    }).catchError((_) {
      // 代表使用者拒絕提供位置資訊或是獲取資訊有錯誤,因此我們要給予一個預設的值
      initialCameraPosition = Config.defaultCameraPosition;
      isPermissionAllowed = true;
    }).whenComplete(() {
      // 不管有沒有錯誤最後都會進到這裡
      // 這裡我們要進到下一個畫面
      Get.offNamed(
        Routes.homeRoute,
        // 將我們在這裡得到的資訊傳到下一個頁面
        arguments: HomePageArgs(
          initialCameraPosition: initialCameraPosition,
          isPermissionAllowed: isPermissionAllowed,
        )
      );
    });
  }
}

GetX 路徑

GetX有提供許多轉換畫面的方法,根據不同的情境可以搭配使用。
  • Get.offNamed: 移除當前的畫面並進入到下一頁,因為我們不希望使用者再回到Splash畫面,因此將他移除,當然我們也可以透過WillPopScope來防止使用者透過Android back按鍵或是iPhone的向右滑回到上一頁,但因為我們也不需要保留這個頁面,所以選擇這個方法。
剩下的方法大家可以到GetX的網站去看,他有提供許多種語言的文件方便大家閱讀。
今天就先做到這裡,如果有任何問題、錯誤或是希望我介紹的主題都可以留言告訴我,謝謝!
avatar-img
3會員
2內容數
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
貓俠的沙龍 的其他內容
如果你是剛入門Flutter的工程師,可以參考這篇文章,我會告訴大家自己常用的套件以及如何規劃檔案的分類!
如果你是剛入門Flutter的工程師,可以參考這篇文章,我會告訴大家自己常用的套件以及如何規劃檔案的分類!
你可能也想看
Google News 追蹤
Thumbnail
本文探討了複利效應的重要性,並藉由巴菲特的投資理念,說明如何選擇穩定產生正報酬的資產及長期持有的核心理念。透過定期定額的投資方式,不僅能減少情緒影響,還能持續參與全球股市的發展。此外,文中介紹了使用國泰 Cube App 的便利性及低手續費,幫助投資者簡化投資流程,達成長期穩定增長的財務目標。
Thumbnail
Flutter is a powerful, open-source UI software development kit created by Google.
Thumbnail
解析成List List items=json.decode(jsonStr); print(items[0]["your_key"]); 解析成Map Map<String, dynamic> user = json.decode(json); print('${user['your_k
Thumbnail
這邊會使用WebSocketChannel去與http://www.websocket.org做連線。 連線 final channel = IOWebSocketChannel.connect('wss://echo.websocket.events'); 接收 StreamBui
Thumbnail
Dio是一個Dart Http請求庫,支援Restful API、FormData、攔截器、請求取消、Cookie管理、檔案上傳/下載、逾時等。 加入 dependencies: dio: ^x.x.x #请使用pub上的最新版本 使用 GET Response response;
Thumbnail
配置 idleTimeout:在httpClient請求結束後,會繼續保持連線,直到超過idleTimeout值才會關閉連接。 connectionTimeout:和伺服器建立連線逾時,如果超過connectionTimeout值則會拋出SocketException異常。 maxConnec
Thumbnail
我將休息、運動的概念引進給考生,一度讓老師覺得不妥,在我的視角:好的身體才有努力的本錢。
Thumbnail
1.項目介紹 Bitget 是領先世界的加密貨幣衍生品交易平台。立即在Bitget 購買比特幣和以太幣,開始您的加密交易之旅! 2.影片介紹 3.小礦工挖挖礦 所有社群連結 https://linktr.ee/TinyTinyMiner
Thumbnail
大學有很多活動、想做的事情攤在眼前,怎麼樣過濾篩選哪些事情能同時符合現實、成長以及興趣?
Thumbnail
藥師通常從廠商來函或是業務代表通知而取得藥品短缺訊息,民眾若想要掌握相關較完整訊息,可以至食藥署「藥品供應資訊平台」(食藥署首頁 > 業務專區 > 藥品 > 通報專區,網址: https://dsms.fda.gov.tw/)。
Thumbnail
理工至上似乎在另一群高薪人的眼中是「奴工」的代表。如果可能的選項都沒有不好,怎麼選?
Thumbnail
本文探討了複利效應的重要性,並藉由巴菲特的投資理念,說明如何選擇穩定產生正報酬的資產及長期持有的核心理念。透過定期定額的投資方式,不僅能減少情緒影響,還能持續參與全球股市的發展。此外,文中介紹了使用國泰 Cube App 的便利性及低手續費,幫助投資者簡化投資流程,達成長期穩定增長的財務目標。
Thumbnail
Flutter is a powerful, open-source UI software development kit created by Google.
Thumbnail
解析成List List items=json.decode(jsonStr); print(items[0]["your_key"]); 解析成Map Map<String, dynamic> user = json.decode(json); print('${user['your_k
Thumbnail
這邊會使用WebSocketChannel去與http://www.websocket.org做連線。 連線 final channel = IOWebSocketChannel.connect('wss://echo.websocket.events'); 接收 StreamBui
Thumbnail
Dio是一個Dart Http請求庫,支援Restful API、FormData、攔截器、請求取消、Cookie管理、檔案上傳/下載、逾時等。 加入 dependencies: dio: ^x.x.x #请使用pub上的最新版本 使用 GET Response response;
Thumbnail
配置 idleTimeout:在httpClient請求結束後,會繼續保持連線,直到超過idleTimeout值才會關閉連接。 connectionTimeout:和伺服器建立連線逾時,如果超過connectionTimeout值則會拋出SocketException異常。 maxConnec
Thumbnail
我將休息、運動的概念引進給考生,一度讓老師覺得不妥,在我的視角:好的身體才有努力的本錢。
Thumbnail
1.項目介紹 Bitget 是領先世界的加密貨幣衍生品交易平台。立即在Bitget 購買比特幣和以太幣,開始您的加密交易之旅! 2.影片介紹 3.小礦工挖挖礦 所有社群連結 https://linktr.ee/TinyTinyMiner
Thumbnail
大學有很多活動、想做的事情攤在眼前,怎麼樣過濾篩選哪些事情能同時符合現實、成長以及興趣?
Thumbnail
藥師通常從廠商來函或是業務代表通知而取得藥品短缺訊息,民眾若想要掌握相關較完整訊息,可以至食藥署「藥品供應資訊平台」(食藥署首頁 > 業務專區 > 藥品 > 通報專區,網址: https://dsms.fda.gov.tw/)。
Thumbnail
理工至上似乎在另一群高薪人的眼中是「奴工」的代表。如果可能的選項都沒有不好,怎麼選?