現實類比:公司打印機
假設你們公司有一臺共享打印機:
非單例(重復創建):
- 每個員工都自己買一臺打印機放在工位上
- 結果:浪費錢,占空間,難維護
單例(唯一實例):
- 全公司只買一臺打印機,放在公共區域
- 所有人都用這臺打印機
- 結果:省錢,省空間,統一管理
代碼中的單例
在 Flutter 中,如果不使用單例,每次調用?new Calculator()
?都會創建一個新的計算器:
// 非單例:創建多個計算器實例
final calc1 = new Calculator();
final calc2 = new Calculator();print(calc1 == calc2); // false,兩個不同的實例
而使用?Get.put()
?注冊的對象默認是單例,無論獲取多少次都是同一個實例:
// 單例:只創建一個計算器實例
Get.put(Calculator());final calc1 = Get.find<Calculator>();
final calc2 = Get.find<Calculator>();print(calc1 == calc2); // true,同一個實例
為什么需要單例?
節省資源:
比如網絡請求控制器、數據庫連接、配置信息等,創建多個實例會浪費內存。數據一致性:
所有地方都使用同一個實例,保證數據狀態統一。
(比如用戶登錄狀態、購物車數據)避免沖突:
某些類只能有一個實例(如打印機、文件系統),否則會引發沖突。
1.?Get.put()
功能:把一個對象「注冊」到 GetX 的全局容器中,讓它在整個應用里都能被訪問。
類比:把工具放進「公共工具箱」,其他人隨時可以取。
特點:默認創建單例(全局唯一實例)。
// 創建并注冊一個控制器(放入工具箱)
Get.put(PostController());// 在其他地方獲取已注冊的控制器
final controller = Get.find<PostController>();
2.?Get.find()
功能:從 GetX 的全局容器中「獲取」已注冊的對象。
類比:從「公共工具箱」里取出需要的工具。
注意:必須先?Get.put()
?注冊,才能?Get.find()
?獲取。
// 獲取已注冊的控制器(從工具箱取工具)
final controller = Get.find<PostController>();// 使用控制器的方法
controller.fetchPosts();
3.?Get.snackbar()
功能:顯示一個頂部或底部的消息提示(類似 Toast 或 Snackbar)。
類比:在屏幕上彈一個「臨時通知」。
特點:支持自定義樣式、持續時間、點擊事件等。
// 顯示一個簡單的消息提示
Get.snackbar('標題', // 標題'這是消息內容', // 內容duration: Duration(seconds: 3), // 顯示3秒snackPosition: SnackPosition.BOTTOM, // 顯示在底部
);
完整示例
// 1. 注冊控制器(通常在頁面初始化時)
Get.put(PostController());// 2. 獲取控制器并調用方法
final controller = Get.find<PostController>();
controller.fetchPosts(); //PostController是class fetchPosts是方法// 3. 在合適的時機顯示消息提示(如點擊按鈕后)
Get.snackbar('加載完成','已成功獲取 ${controller.posts.length} 條數據',snackPosition: SnackPosition.TOP,
);