| کانال توسعه‌دهندگان فلاتر |
1.95K subscribers
34 photos
1 video
16 links
⭕️ کانال توسعه‌دهندگان فلاتر دولوپیکس

💠 دولوپیکس | جامعه توسعه‌دهندگان ایرانی

💎 @Developix
🚀 Developix.ir

📌 پشتیبانی و تبلیغات:
@DevelopixSupport
Download Telegram
🖼️ فلاتر چیست؟

اگر شما یک توسعه‌دهنده اپلیکیشن‌های موبایل هستید یا به دنبال یادگیری یک فریمورک جدید برای ساخت اپلیکیشن‌ها هستید، فلاتر (Flutter) یکی از بهترین انتخاب‌ها برای شماست! 🧑‍💻

چرا فلاتر؟
🤔
فلاتر فریمورکی متن‌باز است که توسط گوگل توسعه یافته و به شما اجازه می‌دهد با یک بار کدنویسی، اپلیکیشن‌های اندروید و iOS بسازید. از ویژگی‌های اصلی فلاتر می‌توان به موارد زیر اشاره کرد:

🔵کدنویسی یک‌باره برای همه پلتفرم‌ها: یک بار کد بنویسید و آن را برای سیستم‌عامل‌های مختلف اجرا کنید.
رابط کاربری زیبا: با فلاتر می‌توانید اپلیکیشن‌هایی با UI جذاب و کاربرپسند طراحی کنید.
🔵سرعت توسعه بالا: به دلیل ویژگی Hot Reload، می‌توانید تغییرات کد را بلافاصله مشاهده کنید.
🔵پشتیبانی قوی: گوگل و جامعه بزرگی از توسعه‌دهندگان از فلاتر پشتیبانی می‌کنند.

چه کسانی باید از فلاتر استفاده کنند؟
💡
🔵توسعه‌دهندگان موبایل که به دنبال ساده‌تر کردن فرآیند توسعه برای چند پلتفرم هستند.
🔵استارتاپ‌ها و کسب‌وکارهای کوچک که می‌خواهند در کمترین زمان و با کمترین هزینه اپلیکیشن خود را ارائه دهند.
🔵توسعه‌دهندگان وب که به دنبال گسترش دامنه مهارت‌های خود به توسعه اپلیکیشن‌های موبایل هستند.

💎 Channel: @DevelopixFlutter
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5
اصلی‌ترین مزیت Flutter چیست؟ سرعت اجرای برنامه را می‌توان مهم‌ترین مزیت فلاتر دانست. درواقع، با تولید یک برنامه می‌توانید خروجی‌های مختلف بگیرید، بدون اینکه به صرف هزینه و زمان بسیار برای هر خروجی نیاز داشته باشید. برخی دیگر از مزایای فلاتر بدین‌شرح‌اند:

۱. رابط کاربری منعطف ☺️
منظور از رابط کاربری منعطف در فلاتر این است که در سریع‌ترین زمان با ساده‌ترین اقدامات می‌توانید ظواهر خلاقانه و پیچیده‌ در برنامه به‌وجود بیاورید؛ اقداماتی که پیاده‌سازی آن‌ها با زبان‌های بومی نه‌تنها دشوار و زمان‌بر است؛ بلکه گاهی اوقات غیرممکن به‌نظر می‌رسد.

۲. برخورداری از مستندات کامل 💬
«منظور از برخورداری مستندات کامل در فلاتر چیست؟» برای استفاده از تکنولوژی جدید، بهره‌مندی از مستندات کامل بسیار اهمیت دارد. خبر خوش درباره فلاتر این است که همه‌چیز با مثال‌های ساده و آسان در مستندات این فریم‌ورک فراهم است. هربار مشکلی در استفاده از فلاتر برایتان به‌وجود بیاید، با مراجعه به مستندات می‌توانید پاسخ مسئله‌تان را پیدا کنید.

۳. متن‌باز و رایگان بودن تمام ابزارک‌ها ⭐️
فریم‌ورک فلاتر و زبان ‌برنامه‌نویسی دارت هر دو منبع‌باز و رایگان هستند. منبع‌باز‌بودن این فریم‌ورک باعث شده است تا متخصصان و برنامه‌نویسان برای بهبود عملکرد آن، مستند قدرتمندی برای فلاتر ایجاد کنند.
درواقع، فلاتر مانند جامعه‌ای در حال رشد است که در آن، برنامه‌نویسان و متخصصان خبره دیدگاه‌ها و تجربه‌های خود از این تکنولوژی کاربردی را تبادل می‌کنند. با مراجعه به مخزن گیت‌هاب یا انجمن‌های فلاتر یا وب‌سایت Flutter AWesome، می‌توانید از تجربیات افراد متخصص در‌زمینه کار با فلاتر بهره‌مند شوید.

۴. امکان ساخت برنامه‌های چندپلتفرمی 🔥
در فلاتر این امکان وجود دارد که با کدنویسی برای هر دو نسخه اندروید و IOS از آن کد استفاده کنید و درواقع، به سوئیچ‌کردن بین پلتفرم‌های مختلف با فلاتر نیازی نیست. حال فایده ساخت برنامه‌های چندپلتفرمی با فلاتر چیست؟ با بهره‌مندی از این ویژگی فلاتر، از آن برای ساخت برنامه‌های تحت‌وب نیز می‌توانید استفاده کنید. بدین‌ترتیب، تا حد زیادی در انرژی و زمان شما برای توسعه برنامه صرفه‌جویی خواهد شد.

۵. سازگاری چشمگیر با استارتاپ‌های MVP 💡
استارتاپ‌های MVP استارتاپ‌هایی هستند که قصد دارند محصولی با پذیرش حداقلی در سریع‌ترین زمان ارائه دهند. در این شرایط، فلاتر گزینه مناسبی برای توسعه اپلیکیشن به‌شمار می‌رود. کاربرد فریم‌ورک فلاتر در استارتاپ‌های MVP چیست؟ به‌بیان ساده، با کمک فلاتر می‌توانید بدون نیاز به تولید و نگه‌داری دو اپلیکیشن در پلتفرم‌های اندروید و IOS، آن را با هزینه ارزان و در سریع‌ترین زمان و با کارایی و جذابیت بصری خیره‌کننده طراحی کنید.

🔖 #Flutter, #فلاتر

💎 Channel: @DevelopixFlutter
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤3🔥2
پکیج Flutter با نام button_animation_plus به شما امکان می‌دهد که دکمه‌های زیبا و تعاملی با افکت‌های انیمیشنی جذاب ایجاد کنید. این پکیج طراحی شده تا با استفاده از فکت‌های مختلف مثل  Shimmer،  Border Animation به دکمه‌های اپلیکیشن شما جلوه‌ای حرفه‌ای و مدرن بدهد.

ویژگی‌های اصلی:
Shimmer: ایجاد افکت درخشش روی دکمه.
Border Animation: تنظیم حرکت انیمیشن روی مرزهای دکمه.
سفارشی‌سازی بالا: امکان تنظیم رنگ‌ها، شعاع مرز، و زاویه‌های انیمیشن.

link: https://pub.dev/packages/button_animation_plus

🔖 #Flutter, #فلاتر

💎 Channel: @DevelopixFlutter
👍17❤3👎1
دیزاین سیستم مجموعه‌ای از قوانین، کامپوننت‌ها و دستورالعمل‌های از پیش تعیین شده‌ است که به تیم‌های طراحی و توسعه کمک می‌کند تا محصولات را با سرعت بیشتر و هماهنگی بهتر ایجاد کنند. این سیستم باعث می‌شود طراحی‌ها یک‌دست و با‌ کیفیت باشند و نیاز به شروع مجدد از صفر کاهش یابد

⚜ توی این پست ما از ابتدا یک دیزاین سیستم رو توی فلاتر پیاده سازی می‌کنیم
🔗 vrgl.ir/oAWDp

🔖 #Flutter, #فلاتر

👤 Morteza Nazari

💎 Channel: @DevelopixFlutter
👍12❤2
📌 ساخت یک صفحه Login حرفه‌ای با Flutter & Riverpod

توی خیلی از اپ‌ها، اولین چیزی که کاربر می‌بینه صفحه Login هست. اگر این صفحه کند، شلوغ یا باگ‌دار باشه، کل تجربه خراب می‌شه. برای همین این پست روی یه سناریوی خیلی واقعی تمرکز می‌کنه: ساخت صفحه Login تمیز و قابل تست با استفاده از Riverpod برای مدیریت state.

🎯 ایده کلی از نمونه‌کد رسمی Riverpod الهام گرفته شده:
Example: multiprovider_login

اینجا هدف اینه که:

• منطق اعتبارسنجی (Validation) از UI جدا باشه ✅
• وضعیت دکمه Login (در حال لود، خطا، موفقیت) واضح مدیریت بشه ✅
• بعداً بشه راحت تست واحد و تست UI نوشت ✅

اول یک StateNotifier برای مدیریت وضعیت فرم می‌سازیم؛ شامل email، password، در حال لود بودن و پیام خطا:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class LoginState {
final String email;
final String password;
final bool isLoading;
final String? error;

const LoginState({
this.email = '',
this.password = '',
this.isLoading = false,
this.error,
});

LoginState copyWith({
String? email,
String? password,
bool? isLoading,
String? error,
}) {
return LoginState(
email: email ?? this.email,
password: password ?? this.password,
isLoading: isLoading ?? this.isLoading,
error: error,
);
}
}

class LoginController extends StateNotifier<LoginState> {
LoginController() : super(const LoginState());

void emailChanged(String value) {
state = state.copyWith(email: value, error: null);
}

void passwordChanged(String value) {
state = state.copyWith(password: value, error: null);
}

Future<void> submit() async {
if (state.email.isEmpty || state.password.isEmpty) {
state = state.copyWith(error: 'فیلدها را پر کنید');
return;
}
state = state.copyWith(isLoading: true, error: null);

await Future.delayed(const Duration(seconds: 1));

state = state.copyWith(isLoading: false);
}
}

final loginProvider =
StateNotifierProvider<LoginController, LoginState>((ref) {
return LoginController();
});


حالا توی UI فقط به state گوش می‌دیم و براساسش ویجت‌ها رو رندر می‌کنیم؛ بدون if/else‌های شلوغ توی همون کلاس:

• isLoading فعال بشه، روی دکمه CircularProgressIndicator نشون می‌دیم.
• اگر error خالی نباشه، یک Text قرمز پایین فرم نشون داده می‌شه.

Docs رسمی Riverpod برای درک عمیق‌تر StateNotifier:
StateNotifierProvider Docs

این ساختار توی پروژه‌های واقعی خیلی کمک می‌کنه، مخصوصاً وقتی بعداً بخوای Login واقعی با API، Token و Error handling جدی اضافه کنی.

امتحانش روی یک صفحه ساده Login توی پروژه‌ی Flutter و Riverpod نتیجه خیلی محسوسی رو توی تمیزی کد و قابلیت توسعه بعدی نشون می‌ده. 🚀

اگر روی Login پیچیده، فرم‌های چندصفحه‌ای یا Auth flow کار می‌شه، این الگو یه پایه خیلی خوب برای ادامه راهه.

🔖 #Flutter #فلاتر #Flutter #Riverpod #Login #State_Management #Dart #Mobile

👤 Developix

💎 Channel: @DevelopixFlutter
❤9🔥1
‏🧩 اسکرول روان‌تر با const widget در ListView

خیلی وقت‌ها لیست‌هامون (ListView / ListView.builder) بی‌دلیل سنگین و کند می‌شن، مخصوصاً وقتی آیتم‌هاتون پیچیده‌ست. یک ترفند ساده برای کم کردن rebuild و بهتر شدن performance اینه که تا جایی که ممکنه از const استفاده بشه.

وقتی یک widget رو const می‌کنید، فلاتر می‌فهمه که این widget تغییری نمی‌کنه و لازم نیست هر بار که parent rebuild می‌شه، دوباره ساخته بشه. این روی لیست‌ها تأثیر خیلی خوبی داره. 🚀

مثال ساده👇

class MyListPage extends StatelessWidget {
const MyListPage({super.key});

@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return const _MyListItem();
},
);
}
}

class _MyListItem extends StatelessWidget {
const _MyListItem({super.key});

@override
Widget build(BuildContext context) {
return ListTile(
leading: const Icon(Icons.person),
title: const Text('User'),
subtitle: const Text('Subtitle'),
);
}
}


نکته مهم ✅

اگر محتوای آیتم وابسته به index یا state متغیر است، کل آیتم رو const نکن، فقط بخش‌های ثابت رو const بگذار:

itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.person),
title: Text('User $index'),
);
}


به همین سادگی تعداد objectهای جدید کمتر می‌شه، زباله‌جمع‌کن (GC) فشار کمتری می‌خوره و UI روان‌تری تجربه می‌شه، مخصوصاً روی دستگاه‌های ضعیف‌تر. 🔧

امتحانش روی لیست‌های سنگین یا صفحه‌هایی که زیاد rebuild می‌شن نتیجه قابل توجهی می‌ده.

مرجع رسمی:
Flutter Performance Best Practices - const widgets

🔖 #Flutter #فلاتر #Flutter #Performance #ListView #Dart #const #UI

👤 Developix

💎 Channel: @DevelopixFlutter
👍8❤7
سوال:
کد زیر را در نظر بگیرید (فرض کنید این کد داخل یک پروژه Flutter اجرا می‌شود، مثلاً در تابع main یا یک تست واحد):

خروجی نهایی این کد در کنسول (stdout) چه خواهد بود؟ ترتیب و متن دقیق هر خط را بنویسید.

توجه کنید که از Future و scheduleMicrotask و Future.microtask استفاده شده و ترتیب اجرای event queue و microtask queue اهمیت دارد.


🔖 #Flutter #فلاتر

👤 Developix

💎 Channel: @DevelopixFlutter
🔥3
یک قطعه کد Dart مربوط به Flutter زیر را ببین:

سؤال:
خروجی نهایی اجرای این کد چیست؟
(به فاصله‌ها و خط‌های جدید در خروجی دقت کن)

راهنما: این کد از event loop، microtask و scheduleMicrotask در Dart استفاده می‌کند.

🔖 #Flutter #فلاتر

👤 Developix

💎 Channel: @DevelopixFlutter
❤4
به این کد دقت کنید:

در نسخهٔ اول، برای هر build یک StreamSubscription جدید ساخته می‌شود و در dispose فقط آخرین مقدار نگه‌داری‌شده لغو می‌شود؛ این کار هم باعث Memory Leak می‌شود هم ممکن است چندین بار listener روی یک Stream داشته باشید و منجر به باگ‌های عجیب در UI شود.

در نسخهٔ دوم با انتقال listen به initState و نگه‌داری subscription در یک فیلد، از ساخت subscriptionهای تکراری جلوگیری شده و چرخهٔ حیات ویجت با Stream به‌درستی مدیریت می‌شود.

سؤال: در چنین سناریوهایی چرا استفاده از initState برای اتصال به Stream و آزاد کردن آن در dispose نسبت به ساخت subscription در متد build هم از نظر کارایی و هم از نظر پایداری برنامه انتخاب بهتری است؟

🔖 #Flutter #فلاتر

👤 Developix

💎 Channel: @DevelopixFlutter
❤3
📱 سوال برای Flutter Devها

خروجی اجرای کد زیر در Dart چیست؟

به ترتیب خط‌ها و دقیقا همان چیزی که در console چاپ می‌شود را بنویسید.

نکته: به رفتار Future، حلقه‌ها و then دقت کنید؛ ترتیب اجرا ساده نیست 🙂

🔖 #Flutter #فلاتر

👤 Developix

💎 Channel: @DevelopixFlutter
👎1
جدا کردن لایه UI از لایه منطق با Provider در Flutter 🧠👉📱

یکی از مهم‌ترین اصول Clean Architecture این است که UI و منطق (Business Logic) را قاطی هم نکنیم. تو Flutter خیلی وقت‌ها تمام منطق، فراخوانی API و state داخل همون فایل Widget اصلی می‌مونه و به‌مرور تبدیل می‌شود به یک God Widget که نگهداری‌اش سخت است 😅

یک راه‌حل ساده و استاندارد در Flutter استفاده از ChangeNotifier + Provider است. ایده اصلی:

• Widget فقط UI را رندر کند 🎨
• کلاس جداگانه state را مدیریت کند و منطق را در خود نگه دارد 🧩

۱. ساخت ViewModel (لایه منطق)
class CounterViewModel extends ChangeNotifier {
int _count = 0;

int get count => _count;

void increment() {
_count++;
notifyListeners();
}
}


اینجا هیچ خبری از BuildContext یا Widget نیست؛ فقط منطق و state. همین جداسازی ساده تست‌نویسی و نگهداری را خیلی راحت‌تر می‌کند ✅

۲. ثبت Provider در ریشه اپ
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => CounterViewModel(),
child: MaterialApp(
home: CounterPage(),
),
);
}
}


الان هر Widget زیرمجموعه می‌تواند به‌صورت امن و تمیز به CounterViewModel دسترسی داشته باشد.

۳. UI تمیز و سبک
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final viewModel = context.watch<CounterViewModel>();

return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: Center(
child: Text(
'Count: ${viewModel.count}',
style: const TextStyle(fontSize: 32),
),
),
floatingActionButton: FloatingActionButton(
onPressed: viewModel.increment,
child: const Icon(Icons.add),
),
);
}
}


توجه کنید که این Widget:
• هیچ state داخلی با setState() ندارد
• فقط از ViewModel می‌خواند و متدهای آن را صدا می‌زند

نکات مهم برای Clean Code با Provider ✨
• منطق async مثل call به API را در ViewModel قرار دهید، نه داخل Widget.
• هر صفحه شلوغ را به چند ViewModel کوچک‌تر و تخصصی تقسیم کنید.
• از context.select<T, R>() برای listen کردن به بخشی از state استفاده کنید تا rebuildها کم شود.

مستندات رسمی Provider و الگوهای پیشنهادی Flutter را می‌توان اینجا دید:
flutter.dev – State management

این جداسازی ساده، قدم بزرگی به سمت معماری تمیز، تست‌پذیر و مقیاس‌پذیر در پروژه‌های Flutter است. از همین امروز در یکی از صفحات شلوغ پروژه‌ات پیاده‌اش کنید و احساس سبکی کد را ببینید 🚀

🔖 #Flutter #فلاتر #Flutter #Clean_Code #Provider #State_Management #Architecture #Dart

👤 Developix

💎 Channel: @DevelopixFlutter
❤6🔥1
🔍 در کد زیر یک Memory Leak و استفاده‌ی اشتباه از Timer در یک StatefulWidget وجود دارد که می‌تواند باعث کرش یا رفتار غیرقابل‌پیش‌بینی در اپ شود. به‌طوری که بعد از ترک صفحه، تایمر همچنان در حال اجرا می‌ماند و به setState روی یک State تخریب‌شده صدا می‌زند.

چه چیزی باید در این کد اصلاح شود تا هم Memory Leak برطرف شود و هم مدیریت Timer به‌درستی انجام شود؟

🔖 #Flutter #فلاتر

👤 Developix

💎 Channel: @DevelopixFlutter
👍6👎2
در نمونه‌کد بالا در نسخهٔ اشتباه، برای هر rebuild ویجت، یک Stream جدید ساخته می‌شود و listen روی آن ثبت می‌گردد که هم باعث Memory Leak می‌شود و هم روی کارایی اسکرول و رندر لیست تأثیر منفی می‌گذارد. در نسخهٔ بهینه با نگه‌داشتن Stream در State و استفاده از StreamBuilder تنها یک بار استریم ساخته شده و مدیریت subscription و cancel به صورت امن انجام می‌شود. این روش هم کد را تمیزتر می‌کند و هم در لیست‌های بزرگ، فشار روی GC و Scheduler را کاهش می‌دهد.

🔹 پرسش: اگر بخواهید در یک صفحهٔ پیچیده با چندین Stream مختلف، این الگو را به شکل تمیزتر و قابل تست‌تر پیاده‌سازی کنید، ترجیح می‌دهید از چه معماری یا State Managementای (مثل Bloc، Riverpod، Cubit و غیره) استفاده کنید و چرا؟

🔖 #Flutter #فلاتر

👤 Developix

💎 Channel: @DevelopixFlutter
Forwarded from ابر ویراک
ویراک کلود | تجربه‌ی ابری بدون محدودیت ☁️🚀

🎁 ۲۰٪ شارژ هدیه روی اولین واریزی

مزیت‌هایی که واقعاً فرق می‌سازن:
⚡️ پهنای باند 980 مگ
🌐با IP مازاد
⏱️ راه‌اندازی فوری
💳 پرداخت ساعتی
🛡 پشتیبانی ۲۴/۷

💬 هر سوالی داشتی، تیم ما کنارتـه
✅ مناسب استارتاپ‌ها، تیم‌های فنی، تا سازمان‌های بزرگ

همین الان شروع کن و با حداکثر منابع، سریع‌تر رشد کن 👇🏻

📞 تماس سریع: 02191555530
🔗 https://virakcloud.com
❤1
‏اصل Single Responsibility توی ویجت‌های Flutter 🧩

یکی از راحت‌ترین راه‌ها برای تمیز و قابل‌نگهداری موندن کد Flutter اینه که واقعاً به Single Responsibility Principle (SRP) پایبند بمونیم.

طبق SRP هر کلاس باید فقط یک دلیل برای تغییر داشته باشه. توی Flutter یعنی هر ویجت بهتره فقط روی یک نقش مشخص تمرکز کنه: نمایش، منطق، یا مدیریت state؛ نه همۀ این‌ها با هم. 😄

وقتی یه صفحه همه‌چیزو قاطی خودش نگه می‌داره:
- تست‌نویسی سخت می‌شه
- ریفکتور خطرناک‌تر می‌شه
- کامپایل hot-reload کندتر حس می‌شه

نمونه‌ی یه ویجت خلاف SRP 👇
class ProfilePage extends StatefulWidget {
const ProfilePage({super.key});

@override
State<ProfilePage> createState() => _ProfilePageState();
}

class _ProfilePageState extends State<ProfilePage> {
bool _loading = false;
String? _name;

Future<void> _loadProfile() async {
setState(() => _loading = true);
await Future.delayed(const Duration(seconds: 1));
setState(() {
_name = 'Ali';
_loading = false;
});
}

@override
void initState() {
super.initState();
_loadProfile();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Profile')),
body: Center(
child: _loading
? const CircularProgressIndicator()
: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(_name ?? 'Unknown'),
ElevatedButton(
onPressed: _loadProfile,
child: const Text('Reload'),
),
],
),
),
);
}
}


اینجا یک کلاس هم:
- API call شبیه‌سازی می‌کنه
- state رو نگه می‌داره
- UI کامل صفحه رو می‌سازه

حالا همون ایده رو با احترام به SRP تکه‌تکه می‌کنیم 👇

۱) جدا کردن منطق لود پروفایل
class ProfileController extends ChangeNotifier {
bool loading = false;
String? name;

Future<void> loadProfile() async {
loading = true;
notifyListeners();

await Future.delayed(const Duration(seconds: 1));

name = 'Ali';
loading = false;
notifyListeners();
}
}


۲) ویجت فقط مسئول نمایش
class ProfilePage extends StatelessWidget {
final ProfileController controller;

const ProfilePage({super.key, required this.controller});

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Profile')),
body: Center(
child: AnimatedBuilder(
animation: controller,
builder: (context, _) {
if (controller.loading) {
return const CircularProgressIndicator();
}
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(controller.name ?? 'Unknown'),
ElevatedButton(
onPressed: controller.loadProfile,
child: const Text('Reload'),
),
],
);
},
),
),
);
}
}


حالا:
- ProfileController فقط منطق و state رو مدیریت می‌کنه
- ProfilePage فقط رندر و تعامل UI رو انجام می‌ده

این الگو با Provider، Riverpod یا BLoC خیلی تمیزتر هم می‌شه و راحت‌تر تست واحد برای منطق می‌نویسیم.

برای مطالعه‌ی بیشتر می‌شه به معماری‌ها و راهنماهای رسمی Flutter سر زد:
State Management - flutter.dev

کم‌کم هر ویجت چاق رو به چند کلاس کوچک با یک وظیفۀ مشخص تبدیل کن و اجازه بده پروژه‌ات در طول زمان بدون ترس از ریفکتور رشد کنه 🚀

🔖 #Flutter #فلاتر #Flutter #Clean_Code #SRP #Architecture #State_Management #Dart

👤 Developix

💎 Channel: @DevelopixFlutter
🔥3