FutureBuilder — ویجتی در Flutter است که به طور خودکار رابط کاربری خود را بر اساس وضعیت فعلی AsyncSnapshot دریافت شده از Future بازسازی میکند. بر خلاف فراخوانی دستی setState پس از await، FutureBuilder رویکرد اعلامی ارائه میدهد: در اولین رندر در Future مشترک میشود و تابع builder را در هر تغییر وضعیت — بارگذاری، خطا یا دادههای آماده — فراخوانی میکند. بر اساس Flutter API Reference (2026)، FutureBuilder به ویژه برای بارگذاری دادهها از شبکه، خواندن از پایگاه داده و هر عملیات ناهمگامی که UI باید نشانگر بارگذاری، پیام خطا یا محتوای آماده نمایش دهد، مفید است.
نکات اصلی
FutureBuilder — یک ویجت داخلی Flutter از بسته widgets است که Future<T> و تابع builder را دریافت میکند. هنگامی که وضعیت Future تغییر میکند (در حال اجرا، تکمیل شده با داده، تکمیل شده با خطا) FutureBuilder به طور خودکار UI را بازسازی میکند و builder را با AsyncSnapshot جدید فراخوانی میکند. این کار نیاز به مدیریت دستی وضعیت بارگذاری از طریق setState و پرچمها را از بین میبرد.
بر خلاف StreamBuilder که با جریانهای داده (Stream) کار میکند، FutureBuilder برای عملیاتهای ناهمگام یکباره طراحی شده است: درخواست HTTP، خواندن از فایل، پرس و جوی پایگاه داده. FutureBuilder خود اشتراک در Future را مدیریت میکند: در اولین ساخت، Future را اجرا میکند و تکمیل آن را پیگیری میکند. هنگام نابودی ویجت، FutureBuilder Future را لغو نمیکند — این مسئولیت توسعهدهنده است.
بر اساس Flutter Cookbook (2026)، FutureBuilder برای مواردی توصیه میشود که عملیات ناهمگام یک بار هنگام مقداردهی اولیه صفحه اجرا میشود. برای عملیاتهای تکراری یا جریانهای داده از StreamBuilder استفاده کنید. هر دو ویجت از الگوی Reactive UI پیروی میکنند، اما FutureBuilder برای درخواستهای یکباره بهینه شده است.
پیادهسازی داخلی FutureBuilder از طریق Future.then و catchError در Future مشترک میشود. در شروع، FutureBuilder connectionState را به ConnectionState.waiting تنظیم میکند و builder را با دادههای خالی فراخوانی میکند. در تکمیل موفق، connectionState به ConnectionState.done با داده تغییر میکند. در صورت خطا، snapshot.error با شیء خطا پر میشود. هر تغییر باعث بازسازی ویجت میشود.
AsyncSnapshot — یک شیء ظرف است که FutureBuilder در هر تغییر وضعیت به تابع builder منتقل میکند. این شیء حاوی تمام اطلاعات درباره وضعیت فعلی عملیات ناهمگام است: آیا بارگذاری ادامه دارد، چه دادههایی دریافت شده، آیا خطایی رخ داده است. درک AsyncSnapshot کلید ساخت صحیح UI با FutureBuilder است.
| ویژگی | نوع | توضیحات |
|---|---|---|
| connectionState | ConnectionState | وضعیت فعلی اتصال (none, waiting, active, done) |
| data | T? | دادههای دریافت شده از Future (null تا تکمیل یا در صورت خطا) |
| error | Object? | شیء خطا در صورت تکمیل Future با استثنا |
| hasData | bool | true اگر data نال نباشد و وضعیت ConnectionState.done باشد |
| hasError | bool | true اگر Future با خطا تکمیل شده باشد |
Enum ConnectionState مرحله عملیات ناهمگام را تعیین میکند. None — وضعیت اولیه هنگامی که Future هنوز اجرا نشده است (به ندرت استفاده میشود، معمولاً در اولین ساخت بدون initialData). Waiting — Future در حال اجراست، دادهها هنوز دریافت نشدهاند. Active — فقط توسط StreamBuilder برای جریانهای با دادههای جزئی استفاده میشود. Done — Future تکمیل شده، دادهها از طریق snapshot.data یا خطا از طریق snapshot.error در دسترس هستند.
مدیریت صحیح همه وضعیتهای AsyncSnapshot در تابع builder — یک نیاز اجباری برای کد تولیدی است. اگر وضعیت waiting را مدیریت نکنید، کاربر در طول بارگذاری صفحه خالی خواهد دید. اگر hasError را مدیریت نکنید، کاربر بدون توضیح Exception دریافت میکند. الگوی توصیه شده: بررسی hasError → بررسی hasData → نمایش پیشفرض بارگذاری.
FutureBuilder را میتوان در چندین الگوی استاندارد استفاده کرد که هر کدام یک کار خاص را حل میکنند. سناریوهای اصلی را بررسی میکنیم: بارگذاری داده هنگام مقداردهی اولیه، بارگذاری با حافظه نهان، درخواستهای موازی و مدیریت خطا با تکرار.
رایجترین الگو — FutureBuilder در متد build StatefulWidget یا StatelessWidget. Future از initState منتقل میشود یا مستقیماً در build ایجاد میشود. مهم است که Future در هر بازسازی در متد build ایجاد نشود — این منجر به درخواستهای تکراری میشود. از Future ذخیره شده در فیلد State استفاده کنید.
برای جلوگیری از درخواستهای تکراری، FutureBuilder را میتوان با CachedNetworkImage یا حافظه نهان محلی ترکیب کرد. پس از اولین بارگذاری، دادهها در حافظه یا SharedPreferences ذخیره میشوند و FutureBuilder دادههای ذخیره شده را فوراً نمایش میدهد و به طور موازی آنها را از شبکه بهروزرسانی میکند. این کار UX را با پاسخ فوری بهبود میبخشد.
بر اساس pub.dev (2026)، ذخیره در حافظه نهان به ویژه برای تصاویر و لیستهای داده مهم است. FutureBuilder با CachedNetworkImageProvider به طور خودکار تصویر ذخیره شده را نمایش میدهد و در صورت عدم وجود، نشانگر بارگذاری با نمایش بعدی فایل دانلود شده را نشان میدهد.
FutureBuilder و مدیریت دستی وضعیت از طریق setState — دو رویکرد به UI ناهمگام در Flutter. هر کدام مزایا و محدودیتهای خود را دارند. انتخاب به پیچیدگی صفحه و تعداد عملیاتهای ناهمگام بستگی دارد.
FutureBuilder در سادگی برنده است: نیازی به اعلام فیلدهای وضعیت بارگذاری، داده و خطا نیست — همه چیز از طریق AsyncSnapshot مدیریت میشود. برای صفحات ساده با یک عملیات ناهمگام ایدهآل است (یک درخواست HTTP، خواندن از پایگاه داده). با این حال، با 5+ عملیات ناهمگام در یک صفحه، FutureBuilder تودرتو بیش از حد ایجاد میکند — یک «هرم» از FutureBuilderهای تودرتو شکل میگیرد.
setState با پرچمهای دستی وضعیت، کنترل و خوانایی بیشتری در منطق پیچیده میدهد. برای صفحات با درخواستهای وابسته متعدد (بارگذاری کاربر → بارگذاری سفارشات او → بارگذاری جزئیات سفارش) بهتر است از setState با ChangeNotifier یا Bloc استفاده کنید. بر اساس Flutter State Management Guide (2026)، برای سناریوهای پیچیده توصیه میشود به جای FutureBuilder از Riverpod یا Bloc استفاده کنید، زیرا آنها جداسازی بهتری بین منطق و نمایش فراهم میکنند.
بیایید یک مثال عملی از FutureBuilder برای بارگذاری لیست کاربران از REST API را بررسی کنیم. کد مدیریت صحیح هر سه وضعیت AsyncSnapshot را نشان میدهد: بارگذاری، خطا و دادههای آماده.
class UserListPage extends StatefulWidget {
const UserListPage({super.key});
@override
State<UserListPage> createState() => _UserListPageState();
}
class _UserListPageState extends State<UserListPage> {
final Future<List<User>> usersFuture = UserRepository().fetchUsers();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('کاربران')),
body: FutureBuilder<List<User>>(
future: usersFuture,
builder: (context, AsyncSnapshot<List<User>> snapshot) {
if (snapshot.hasError) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, size: 48, color: Colors.red),
const SizedBox(height: 16),
Text('خطا: ${snapshot.error}'),
],
),
);
}
if (snapshot.hasData) {
final users = snapshot.data!;
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(backgroundImage: NetworkImage(users[index].avatarUrl)),
title: Text(users[index].name),
subtitle: Text(users[index].email),
);
},
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
در این مثال، FutureBuilder هر سه وضعیت را مدیریت میکند. در صورت خطا، آیکون با پیام خطا نمایش داده میشود. در بارگذاری موفق — ListView با آواتارها و نامها. در طول بارگذاری — CircularProgressIndicator. Future به عنوان فیلد کلاس اعلام شده است که از فراخوانی مجدد در بازسازی جلوگیری میکند. این الگو 90% سناریوهای استفاده از FutureBuilder در برنامههای موبایل را پوشش میدهد.
سوالات متداول
FutureBuilder builder را در هر تغییر وضعیت Future فراخوانی میکند: اولین بار در ایجاد (connectionState: none یا waiting)، دومین بار در تکمیل (connectionState: done). اگر ویجت والد بازسازی شود، FutureBuilder نیز بازسازی میشود. برای جلوگیری از فراخوانیهای تکراری، مطمئن شوید که Future خارج از متد build ایجاد میشود — در غیر این صورت هر فراخوانی build یک Future جدید ایجاد میکند.
Future را در فیلد StatefulWidget (در initState) ذخیره کنید یا از memoization استفاده کنید. اگر Future در داخل متد build ایجاد شود، هر فراخوانی build یک Future جدید ایجاد میکند و FutureBuilder عملیات ناهمگام را دوباره شروع میکند. برای StatelessWidget از بسته cached_future یا ویجتهای keep-alive استفاده کنید تا Future بدون توجه به بازسازیها یک بار اجرا شود.
FutureBuilder برای عملیاتهای ناهمگام یکباره طراحی شده است (یک درخواست HTTP، یک خواندن از پایگاه داده). StreamBuilder با جریانهای داده کار میکند که میتوانند مقادیر متعددی در طول زمان منتشر کنند (چت، بهروزرسانی قیمت، موقعیت جغرافیایی). StreamBuilder از ConnectionState.active برای دادههای جزئی پشتیبانی میکند، در حالی که FutureBuilder فقط waiting و done را پشتیبانی میکند.
برای چند Future موازی از Future.wait استفاده کنید و نتیجه را به یک FutureBuilder منتقل کنید. Future.wait لیستی از Futureها را دریافت میکند و Future<List> برمیگرداند — هنگامی که همه Futureها تکمیل شدند، builder آرایهای از نتایج را دریافت میکند. برای درخواستهای ترتیبی از زنجیره Future.then در یک Future یا FutureBuilderهای تودرتو (کمتر خوانا) استفاده کنید. جایگزین — بسته riverpod با AsyncValue برای حالتهای ناهمگام متعدد.
FutureBuilder Future را به طور خودکار لغو نمیکند. برای لغو از CancelableOperation از بسته async یا مکانیزم خود از طریق پرچم cancelled در State استفاده کنید. در dispose() پرچم را تنظیم کنید و پس از تکمیل Future قبل از فراخوانی setState آن را بررسی کنید. جایگزین، از بسته riverpod با AutoDispose استفاده کنید که به طور خودکار عملیاتهای ناهمگام را هنگام خروج از صفحه لغو میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید