我使用這款人工智慧開發環境打造了三款 Flutter 應用程式(真是瘋狂)


摘要

本文探討使用 Cursor AI 在 Flutter 開發中所帶來的革命性變化,以及其對開發者的重要意義。 歸納要點:

  • 深入分析 Cursor AI 在 Flutter 開發中的實際應用,提供程式碼片段和設計架構的具體案例。
  • 探討 Cursor AI 的大型語言模型如何整合 Flutter 特性,並與其他工具進行性能比較。
  • 評估 Cursor AI 程式碼輔助工具的效能和限制,並提出最佳實踐以提升開發效率。
透過這些深入分析與實務經驗分享,讀者將更了解如何有效利用 Cursor AI 提升 Flutter 專案的開發效率。

過去的整合開發環境(IDE)不過是一些華麗的文字編輯器,但隨著一群人工智慧研究者和工程師決定改變軟體工程界的格局,他們打造了一款功能強大的文字編輯器。如果你偏好觀看影片,我這裡也有相關資源。

我們在研究許多文章後,彙整重點如下
網路文章觀點與我們總結
  • Cursor是一款強大的AI工具,能幫助用戶快速生成程式碼,實現App創意。
  • 即便是程式開發新手,也能透過Cursor輕鬆上手,不需要有深厚的編程背景。
  • Cursor具備自然語言指令與多檔案編輯功能,大幅簡化了程式設計過程。
  • Project IDX則提供類似VS Code的操作介面,支持多種編程語言,包括Flutter、Go等。
  • Anysphere推出的Cursor經歷了多次版本更新,不斷引入新的AI模型提升使用體驗。
  • Cursor將AI深度整合進IDE中,使得開發者在寫程式時更加高效和便捷。

對於想要創建應用程式卻沒有資深技術背景的人來說,Cursor真的是一個福音。這款AI工具不僅讓我們可以輕鬆生成所需的程式碼,更重要的是,它降低了學習門檻,使每個人都能在短時間內實現自己的App夢想。不論你是初學者還是有經驗的開發者,這樣的工具都能讓你的工作變得更有效率!

觀點延伸比較:
工具名稱主要功能編程語言支持適合程度最新趨勢
Cursor快速生成程式碼、自然語言指令、多檔案編輯Flutter、JavaScript、Python等程式開發新手至中級開發者皆可使用AI整合IDE提升效率,持續版本更新引入新模型
Project IDX類似VS Code的操作介面、高度自定義化選項Flutter、Go、Dart等適合有一定基礎的開發者及專業人士使用多語言支持,強調協作與雲端運算
Anysphere Cursor (最新版本)深度整合AI於IDE,提高編碼效率與便捷性多種編程語言,包括Flutter和Node.js等從初學者到高階開發者均能受益於其智能建議功能專注於提升用戶體驗,結合機器學習技術進行即時反饋

Cursor AI 程式碼編輯器:技術剖析、商業模式與未來展望

背後團隊的介紹:Anysphere與Cursor

Anysphere是開發Cursor這款AI文字編輯器的團隊,致力於自動化編碼。儘管是一個小型但人才濃縮的團隊,他們已經發表了重要研究並贏得了奧林匹克獎牌。

Cursor的技術基礎

Cursor是基於Electron平台,使用TypeScript構建在VSCode的開源核心之上。它利用GPT-4和其他AI模型來生成及理解程式碼,提供智慧程式碼補全、重構以及整個專案的全自動程式碼生成。最令人驚訝的是,這一切都是免費提供給使用者的。

安裝Cursor

要安裝Cursor,請前往其官方網站下載。在首次開啟時,它會提示您從VSCode匯入所有設定。

**深入分析Cursor背後技術棧及未來發展趨勢:** Anysphere所公開的資訊顯示,Cursor基於Electron、TypeScript以及VSCode開源核心並不算新鮮,但值得深入探討的是他們在效能最佳化上的策略。Electron應用程式因跨平台特性受到讚譽,但卻常遭批評以效能較低著稱。因此,頂尖專家會關注Anysphere如何克服Electron可能帶來的效能瓶頸,例如是否採用了特定渲染技術(如GPU加速)以提升反應速度? TypeScript程式碼是否經過模組化設計及嚴謹測試與最佳化?

在GPT-4及其他AI模型整合方面也值得仔細分析,比如Anysphere如何管理模型API請求以確保穩定性和響應速度?他們是否建立快取機制或其他最佳化策略,以減少對OpenAI API依賴並降低使用成本?

至於未來發展趨勢,Anysphere是否考慮將核心程式碼從Electron遷移到更輕量級框架,以進一步提高效能,以及探索WebAssembly等技術以增強跨平台相容性,都將成為影響其長期競爭力的重要因素。同樣地,這些決策也關乎使用者在大型專案上使用Cursor時所面臨的穩定性與效率問題。

**對Cursor商業模式及AI模型調校策略的深入分析:** 目前Cursor免費提供服務,在AI輔助編碼工具領域中相當罕見,因此引起了對其商業模式的猜想。頂尖專家會密切關注Anysphere未來盈利策略,例如是否考慮採取增值服務模式(例如提供高階AI模型或專屬支援)?或者尋求與其他公司合作,把Cursor整合進現有開發流程中?

同時,針對程式碼生成、重構和程式碼補全等具體任務微調GPT-4及其他模型,其調校策略也是值得深入探討的一環。他們使用哪些資料集來訓練或微調這些模型?又該怎麼評估這些模型效能呢?

Anysphere如何確保輸出程式碼品質與安全性?他們是否建立完善錯誤偵測和修復機制?如何處理可能產生偏見或錯誤的資訊?這些細節直接影響到Cursor的可靠性和安全性,也是評估其技術實力和長期潛力的重要指標,更是使用者最關心的大議題之一。


使用 Cursor 建立計算器應用程式 我們來嘗試使用 Cursor 在 Flutter 中建立一個計算器應用程式。在 Cursor 中,按下 Command + Shift + P 以開啟命令面板並建立一個新專案。然後前往 main.dart 檔案,選擇一行空白的地方,接著按下 Command + L 開啟聊天選單。


在這裡,您可以與 Cursor 進行對話,並利用您現有專案的背景資訊。您還可以透過點選此按鈕選擇想要使用的 AI 模型,以便更好地理解和生成程式碼。


我選擇了 claude-3.5-sonnet,因為它在編碼基準測試中表現最佳。現在,請提示它建立你的計算器應用程式,而 Cursor 將在聊天面板中構建你的應用。

prompt: "create a calculator app"

一旦程式碼生成完成,您應該可以向下滾動,檢視對該程式碼的解釋及其功能。系統還會詢問您是否希望新增更多功能。如果您對所看到的內容感到滿意,可以直接應用並接受這些程式碼片段。


這將把程式碼應用於建議的檔案,在我的案例中是 main.dart。現在按下 F5 執行應用程式,您應該能看到所有功能都如預期般運作。


建立一個響應式的作品集應用程式(僅限UI)讓我們捨棄這個應用程式,看看Cursor是否能建立一個我非常需要的作品集。再次輸入提示,但這次我也會要求一個響應式的應用程式,而不是簡單的版本。

prompt: "can you create a responsive portfolio app"

一旦程式碼生成後,點選接受,然後儲存檔案並執行應用程式。Cursor 產生了一個看似簡單的投資組合 UI 結構,但有趣的是,它同時也實現了響應式設計。



根據設計圖片生成程式碼聽起來有些無聊。我們來測試一下游標(cursor)如何基於圖片生成程式碼。在聊天面板中,簡單地拖動一張移動應用程式的UI設計圖片,然後寫下提示要求遊標將其製作得畫素完美,接著按下回車鍵。


prompt: "Please revamp my project to create this UI with all the colors and make sure everything is pixel perfect"

接著,遊標將生成所有的程式碼。只需應用並接受建議,然後執行應用程式。它生成了一個畫素完美的使用者介面,但出現了許多執行時錯誤,不過這不重要,因為在我的電腦上它能編譯並看起來很好(呵呵)。


使用領域驅動設計(Domain Driven Design)來生成應用程式的商業邏輯。現在,讓我們給予 Cursor 最終的考驗。我不喜歡程式碼過於冗長而集中在單一檔案中,因此我將要求 AI 以領域驅動設計的架構實現這個金融應用程式,同時我希望模擬資料能夠來自資料庫層。

prompt: "use DDD and make sure sample data comes from the repository"

你應該能夠看到生成的模型和儲存庫方法,但更重要的是,它讓你有選擇將生成的程式碼新增到新檔案中的選項,並且還為這些檔案建立了資料夾和子資料夾。在生成的程式碼中,我可以看到一些編譯錯誤,所以我會修正那些錯誤並執行應用程式。應用程式執行良好,但如果你沒有注意到,這個應用程式將呈現邏輯放在 main.dart 檔案內,而域(domain)和基礎設施層(infrastructure layers)則分別位於不同的資料夾中,但缺少了應用層(application layer)。


所以讓我們引導人工智慧生成一個應用層,使用 bloc 並將我們的元件從有狀態元件轉換為無狀態元件。

prompt: "Please make sure this widget is stateful and add bloc as state management in application layer"

一旦生成後,請像之前一樣應用程式碼更改,但這次它還建議我在 pubspec.yaml 中匯入相關的套件並在終端機中執行 build_runner 命令以生成類別。讓我們這麼做,將 freezed 和 build_runner 套件複製並貼上到 pubspec.yaml 中,然後執行 flutter pub get。接著在終端機中執行 build_runner 命令來生成 freezed 事件和狀態類別:dart run build_runner build -d。現在的程式碼庫擁有無狀態小部件,並且處處使用 bloc 的狀態物件來管理狀態。該專案結構現在也新增了一個 state 資料夾。

//generated code class PortfolioHomePage extends StatelessWidget {   const PortfolioHomePage({super.key});    @override   Widget build(BuildContext context) {     return BlocProvider(       create: (context) => PortfolioBloc(         TransactionRepositoryImpl(),       )..add(const PortfolioEvent.loadData()),       child: const _PortfolioHomePageView(),     );   } }  class _PortfolioHomePageView extends StatelessWidget {   const _PortfolioHomePageView();    @override   Widget build(BuildContext context) {     return Scaffold(       body: SafeArea(         child: BlocBuilder(           builder: (context, state) {             return state.map(               initial: (_) => const Center(child: CircularProgressIndicator()),               loading: (_) => const Center(child: CircularProgressIndicator()),               error: (error) => Center(child: Text(error.message)),               loaded: (data) => Padding(                 padding: const EdgeInsets.fromLTRB(20, 12, 20, 0),                 child: Column(                   crossAxisAlignment: CrossAxisAlignment.start,                   children: [                     // Header with profile and actions                     Row(                       children: [                         const CircleAvatar(                           radius: 24,                           backgroundImage:                               NetworkImage('https://via.placeholder.com/48'),                         ),                         const SizedBox(width: 12),                         const Text(                           'Anthony Jones',                           style: TextStyle(                             fontSize: 20,                             fontWeight: FontWeight.w600,                           ),                         ),                         const Spacer(),                         Container(                           decoration: BoxDecoration(                             color: Colors.white,                             borderRadius: BorderRadius.circular(50),                             boxShadow: [                               BoxShadow(                                 color: Colors.black.withOpacity(0.1),                                 blurRadius: 10,                                 offset: const Offset(0, 2),                               ),                             ],                           ),                           child: IconButton(                             icon: const Icon(Icons.settings_outlined),                             onPressed: () {},                           ),                         ),                         const SizedBox(width: 12),                         Container(                           decoration: BoxDecoration(                             color: Colors.white,                             borderRadius: BorderRadius.circular(50),                             boxShadow: [                               BoxShadow(                                 color: Colors.black.withOpacity(0.1),                                 blurRadius: 10,                                 offset: const Offset(0, 2),                               ),                             ],                           ),                           child: IconButton(                             icon: const Icon(Icons.notifications_outlined),                             onPressed: () {},                           ),                         ),                       ],                     ),                      const SizedBox(height: 32),                      // Balance section                     Column(                       crossAxisAlignment: CrossAxisAlignment.start,                       children: [                         const Text(                           'Available on card',                           style: TextStyle(                             fontSize: 17,                             color: Color(0xFF666666),                             fontWeight: FontWeight.w400,                           ),                         ),                         const SizedBox(height: 8),                         Text(                           '\$${data.balance.toStringAsFixed(2)}',                           style: const TextStyle(                             fontSize: 34,                             fontWeight: FontWeight.w600,                             letterSpacing: -0.5,                           ),                         ),                       ],                     ),                      const SizedBox(height: 24),                      // Transfer limit section                     Container(                       padding: const EdgeInsets.symmetric(vertical: 16),                       decoration: const BoxDecoration(                         border: Border(                           bottom:                               BorderSide(color: Color(0xFFEEEEEE), width: 1),                         ),                       ),                       child: Column(                         crossAxisAlignment: CrossAxisAlignment.start,                         children: [                           Row(                             mainAxisAlignment: MainAxisAlignment.spaceBetween,                             children: [                               const Text(                                 'Transfer Limit',                                 style: TextStyle(                                   fontSize: 17,                                   fontWeight: FontWeight.w500,                                 ),                               ),                               Text(                                 '\$${data.transferLimit.toStringAsFixed(0)}',                                 style: const TextStyle(                                   fontSize: 17,                                   fontWeight: FontWeight.w500,                                 ),                               ),                             ],                           ),                           const SizedBox(height: 8),                           Text(                             'Spent \$${data.spentAmount.toStringAsFixed(2)}',                             style: const TextStyle(                               fontSize: 15,                               color: Color(0xFF666666),                             ),                           ),                         ],                       ),                     ),                      const SizedBox(height: 24),                      // Action buttons                     Row(                       children: [                         Expanded(                           child: ElevatedButton.icon(                             onPressed: () {},                             icon: const Icon(Icons.attach_money, size: 20),                             label: const Text(                               'Pay',                               style: TextStyle(                                   fontSize: 16, fontWeight: FontWeight.w500),                             ),                             style: ElevatedButton.styleFrom(                               foregroundColor: Colors.white,                               backgroundColor: Colors.black,                               padding: const EdgeInsets.symmetric(vertical: 16),                               shape: RoundedRectangleBorder(                                 borderRadius: BorderRadius.circular(12),                               ),                             ),                           ),                         ),                         const SizedBox(width: 16),                         Expanded(                           child: ElevatedButton.icon(                             onPressed: () {},                             icon: const Icon(Icons.add, size: 20),                             label: const Text(                               'Deposit',                               style: TextStyle(                                   fontSize: 16, fontWeight: FontWeight.w500),                             ),                             style: ElevatedButton.styleFrom(                               foregroundColor: Colors.white,                               backgroundColor: Colors.black,                               padding: const EdgeInsets.symmetric(vertical: 16),                               shape: RoundedRectangleBorder(                                 borderRadius: BorderRadius.circular(12),                               ),                             ),                           ),                         ),                       ],                     ),                      const SizedBox(height: 32),                      // Operations section                     Row(                       mainAxisAlignment: MainAxisAlignment.spaceBetween,                       children: [                         const Text(                           'Operations',                           style: TextStyle(                             fontSize: 20,                             fontWeight: FontWeight.w600,                           ),                         ),                         TextButton(                           onPressed: () {},                           child: const Text(                             'View All',                             style: TextStyle(                               color: Color(0xFF6E5DE7),                               fontSize: 16,                               fontWeight: FontWeight.w500,                             ),                           ),                         ),                       ],                     ),                      const SizedBox(height: 16),                      // Transactions list                     ...data.transactions                         .map((transaction) => _buildTransactionItem(                               transaction.title,                               transaction.subtitle,                               '\$${transaction.amount.toStringAsFixed(2)}',                               transaction.logoPath,                             )),                   ],                 ),               ),             );           },         ),       ),       bottomNavigationBar: BottomNavigationBar(         currentIndex: 0,         type: BottomNavigationBarType.fixed,         items: const [           BottomNavigationBarItem(             icon: Icon(Icons.home_filled),             label: 'Home',           ),           BottomNavigationBarItem(             icon: Icon(Icons.insights),             label: 'Insights',           ),           BottomNavigationBarItem(             icon: Icon(Icons.account_balance_wallet),             label: 'Wallet',           ),           BottomNavigationBarItem(             icon: Icon(Icons.more_horiz),             label: 'More',           ),         ],       ),     );   }

Cursor:AI程式碼輔助工具,提升開發效率,告別404錯誤

如果你現在執行這個應用程式,應該能看到一個載入器在資料載入之前出現,這是非常棒的。Cursor 是一個很好的工具,可以讓你開始新專案,而無需擔心繁瑣的樣板程式碼。它還能幫助你維護和處理現有專案,例如透過程式碼補全、重構和修復錯誤。

未來會是什麼樣子呢?我相信軟體工程的正規化正在發生變化,未來將花更少的時間於編碼,而軟體工程師將能夠更多地專注於創造性的工作,而不是解決404行上的錯誤。我建立了一個 Flutter 應用程式,但實際上,你可以使用 Cursor 來開發任何語言和任何平台。不過要小心,我已經超過了本月的免費使用限制,你可以在他們的官方網站上了解更多關於免費限制的資訊。

值得注意的是,Cursor 的 AI 程式碼生成能力與大型語言模型 (LLM) 的整合尤為重要。隨著技術的不斷進步,Cursor 有可能利用 LLM 的語義理解能力,更精確地生成程式碼,它甚至能根據自然語言描述直接產生完整的應用模組。例如,在自動修復錯誤方面,不僅限於泛稱「fixing errors」,而是要深入探討其具體機制;同時在智慧程式碼重構中,如將傳統迴圈改寫成更現代化的函式式程式設計風格等,都顯示了 Cursor 在 AI 輔助開發領域未來競爭力的重要性。

對於不同程式語言(如 Java、C++、Python 和 Go)及平台(如 iOS、Android、Web 和嵌入式系統)的跨平台支援與效能差異,也需要進一步分析。例如,Cursor 在處理不同語言中的程式碼風格及特性上的適應能力如何?在各種平台上生成程式碼的效率和質量是否一致?針對特定語言或平台是否提供最佳化機制?這些問題都需要透過深入分析與測試資料來驗證。大型專案是否會影響 Cursor 的效能以及其程式生成速度與質量是否與專案規模相關,也都是評估其實際應用價值的重要考量。

請在評論中告訴我,你建立了什麼,以及使用 Cursor 的過程如何。和往常一樣,我會將生成的程式碼放在我的 GitHub 上,讓大家可以利用它來造福更多人。希望你在這篇文章中學到了一些新知識,我們下次再見!撰寫這些文章並製作相關影片需要我花費大量時間。現在你可以透過贊助我喝杯咖啡來支援我: https://buymeacoffee.com/rawaha 請在這裡以及我的社交媒體上關注我!Youtube: https://www.youtube.com/@runtimesnippets LinkedIn: https://www.linkedin.com/in/rawahamuhammad/ Github: https://github.com/coffiie Medium: Rawaha Muhammad


參考來源

Cursor AI 顛覆程式開發!零基礎也能快速打造App

零基礎也能快速打造App. Cursor是一款強大的AI工具,能幫助你快速生成程式碼,實現你的App創意。即使你是程式開發新手,也能輕鬆上手.

來源: Tenten Creative

Cursor - The AI Code Editor

Built to make you extraordinarily productive, Cursor is the best way to code with AI. Download for linux. Watch Demo. Trusted by Engineers at ...

來源: Cursor AI

Cursor AI 編輯器爆紅!不會程式碼也可以寫程式

Cursor AI 編輯器迅速走紅,因其強大的AI 編碼輔助功能,即使不懂程式碼的使用者也能輕鬆創建應用程式。透過自然語言指令與多檔案編輯功能,Cursor 大幅簡化了程式設計 ...

來源: learnai.tw

使用線上IDE Project IDX 開發Flutter App | by 彼得潘的iOS App Neverland

Project IDX 有著類似VS Code 的操作介面,它可以開發許多程式,比方Flutter、Go、Python、Node 等,而且它還搭配Google 的AI Gemini 輔助我們寫程式呢。

來源: Medium

【Flutter 學習筆記】如何使用單行與多行註解| HKT實驗室

它不僅能幫助開發者快速了解程式碼的運算邏輯,還能在未來的維護中提供重要的參考。就像在程式碼中貼上便利貼,提醒未來的自己或他人該段程式碼的功能與用途 ...

來源: Vocus

開發者效率狂飆!Cursor AI編輯器可以用聊天的方式,做到和程式碼 ...

為此,Anysphere開發了一個高效的AI 程式設計工具Cursor。 從去年年初發表至今,Cursor經歷了3次重大的版本更新和近40次的功能迭代,不斷引入新的AI 模型 ...

來源: T客邦

Cursor IDE 心得:三大亮點與三個阻礙

Cursor 是一款主打AI 輔助寫程式的新型態IDE,它並非單純在既有編輯器加上外掛,而是將AI 深度整合進編輯器中。 它直接使用了VS Code 的開源程式碼來建構。

來源: Code and Me

GitHub Copilot AI 替代品,12 款不可錯過的程式開發秘密武器

兩三個禮拜後(2024/11 月底)又增加了更多編輯器的支援,市場上常見的Xcode、VS Code、Jetbrains 家族,還有一些CLI 工具像是Terminal、iTerm,也都支援Work ...

來源: blog.user.today

JS

專家

相關討論

❖ 相關專欄