FutureBuilder چیست؟ کار با Future در Flutter

نویسنده: IT Sectr منتشر شده: 2026-07-02 زمان مطالعه: 8 دقیقه

FutureBuilder — ویجتی در Flutter است که به طور خودکار رابط کاربری خود را بر اساس وضعیت فعلی AsyncSnapshot دریافت شده از Future بازسازی می‌کند. بر خلاف فراخوانی دستی setState پس از await، FutureBuilder رویکرد اعلامی ارائه می‌دهد: در اولین رندر در Future مشترک می‌شود و تابع builder را در هر تغییر وضعیت — بارگذاری، خطا یا داده‌های آماده — فراخوانی می‌کند. بر اساس Flutter API Reference (2026)، FutureBuilder به ویژه برای بارگذاری داده‌ها از شبکه، خواندن از پایگاه داده و هر عملیات ناهمگامی که UI باید نشانگر بارگذاری، پیام خطا یا محتوای آماده نمایش دهد، مفید است.

نکات اصلی

  • FutureBuilder — ویجت Flutter برای ساخت UI بر اساس وضعیت Future از طریق AsyncSnapshot (none, waiting, active, done)
  • AsyncSnapshot — شیء حاوی وضعیت فعلی عملیات ناهمگام: connectionState, data و error
  • builder — تابع回调 که در هر تغییر وضعیت Future برای بازسازی UI فراخوانی می‌شود
  • مدیریت خطا — AsyncSnapshot.hasError امکان نمایش رابط جایگزین در صورت شکست عملیات ناهمگام را فراهم می‌کند
  • ConnectionState — enum با چهار مقدار: none (بدون عملیات), waiting (در انتظار), active (جریان), done (تکمیل شده)

FutureBuilder در Flutter چیست

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 چگونه در زیرساخت کار می‌کند

پیاده‌سازی داخلی FutureBuilder از طریق Future.then و catchError در Future مشترک می‌شود. در شروع، FutureBuilder connectionState را به ConnectionState.waiting تنظیم می‌کند و builder را با داده‌های خالی فراخوانی می‌کند. در تکمیل موفق، connectionState به ConnectionState.done با داده تغییر می‌کند. در صورت خطا، snapshot.error با شیء خطا پر می‌شود. هر تغییر باعث بازسازی ویجت می‌شود.

AsyncSnapshot: وضعیت‌ها و ویژگی‌ها

AsyncSnapshot — یک شیء ظرف است که FutureBuilder در هر تغییر وضعیت به تابع builder منتقل می‌کند. این شیء حاوی تمام اطلاعات درباره وضعیت فعلی عملیات ناهمگام است: آیا بارگذاری ادامه دارد، چه داده‌هایی دریافت شده، آیا خطایی رخ داده است. درک AsyncSnapshot کلید ساخت صحیح UI با FutureBuilder است.

ویژگینوعتوضیحات
connectionStateConnectionStateوضعیت فعلی اتصال (none, waiting, active, done)
dataT?داده‌های دریافت شده از Future (null تا تکمیل یا در صورت خطا)
errorObject?شیء خطا در صورت تکمیل Future با استثنا
hasDatabooltrue اگر data نال نباشد و وضعیت ConnectionState.done باشد
hasErrorbooltrue اگر Future با خطا تکمیل شده باشد

ConnectionState: چهار وضعیت عملیات ناهمگام

Enum ConnectionState مرحله عملیات ناهمگام را تعیین می‌کند. None — وضعیت اولیه هنگامی که Future هنوز اجرا نشده است (به ندرت استفاده می‌شود، معمولاً در اولین ساخت بدون initialData). Waiting — Future در حال اجراست، داده‌ها هنوز دریافت نشده‌اند. Active — فقط توسط StreamBuilder برای جریان‌های با داده‌های جزئی استفاده می‌شود. Done — Future تکمیل شده، داده‌ها از طریق snapshot.data یا خطا از طریق snapshot.error در دسترس هستند.

مدیریت صحیح همه وضعیت‌های AsyncSnapshot در تابع builder — یک نیاز اجباری برای کد تولیدی است. اگر وضعیت waiting را مدیریت نکنید، کاربر در طول بارگذاری صفحه خالی خواهد دید. اگر hasError را مدیریت نکنید، کاربر بدون توضیح Exception دریافت می‌کند. الگوی توصیه شده: بررسی hasError → بررسی hasData → نمایش پیش‌فرض بارگذاری.

الگوهای استفاده از FutureBuilder

FutureBuilder را می‌توان در چندین الگوی استاندارد استفاده کرد که هر کدام یک کار خاص را حل می‌کنند. سناریوهای اصلی را بررسی می‌کنیم: بارگذاری داده هنگام مقداردهی اولیه، بارگذاری با حافظه نهان، درخواست‌های موازی و مدیریت خطا با تکرار.

بارگذاری داده هنگام مقداردهی اولیه صفحه

رایج‌ترین الگو — FutureBuilder در متد build StatefulWidget یا StatelessWidget. Future از initState منتقل می‌شود یا مستقیماً در build ایجاد می‌شود. مهم است که Future در هر بازسازی در متد build ایجاد نشود — این منجر به درخواست‌های تکراری می‌شود. از Future ذخیره شده در فیلد State استفاده کنید.

بارگذاری با حافظه نهان و به‌روزرسانی

برای جلوگیری از درخواست‌های تکراری، FutureBuilder را می‌توان با CachedNetworkImage یا حافظه نهان محلی ترکیب کرد. پس از اولین بارگذاری، داده‌ها در حافظه یا SharedPreferences ذخیره می‌شوند و FutureBuilder داده‌های ذخیره شده را فوراً نمایش می‌دهد و به طور موازی آنها را از شبکه به‌روزرسانی می‌کند. این کار UX را با پاسخ فوری بهبود می‌بخشد.

بر اساس pub.dev (2026)، ذخیره در حافظه نهان به ویژه برای تصاویر و لیست‌های داده مهم است. FutureBuilder با CachedNetworkImageProvider به طور خودکار تصویر ذخیره شده را نمایش می‌دهد و در صورت عدم وجود، نشانگر بارگذاری با نمایش بعدی فایل دانلود شده را نشان می‌دهد.

FutureBuilder در مقابل setState: کدام را انتخاب کنیم

FutureBuilder و مدیریت دستی وضعیت از طریق setState — دو رویکرد به UI ناهمگام در Flutter. هر کدام مزایا و محدودیت‌های خود را دارند. انتخاب به پیچیدگی صفحه و تعداد عملیات‌های ناهمگام بستگی دارد.

FutureBuilder در سادگی برنده است: نیازی به اعلام فیلدهای وضعیت بارگذاری، داده و خطا نیست — همه چیز از طریق AsyncSnapshot مدیریت می‌شود. برای صفحات ساده با یک عملیات ناهمگام ایده‌آل است (یک درخواست HTTP، خواندن از پایگاه داده). با این حال، با 5+ عملیات ناهمگام در یک صفحه، FutureBuilder تودرتو بیش از حد ایجاد می‌کند — یک «هرم» از FutureBuilderهای تودرتو شکل می‌گیرد.

setState با پرچم‌های دستی وضعیت، کنترل و خوانایی بیشتری در منطق پیچیده می‌دهد. برای صفحات با درخواست‌های وابسته متعدد (بارگذاری کاربر → بارگذاری سفارشات او → بارگذاری جزئیات سفارش) بهتر است از setState با ChangeNotifier یا Bloc استفاده کنید. بر اساس Flutter State Management Guide (2026)، برای سناریوهای پیچیده توصیه می‌شود به جای FutureBuilder از Riverpod یا Bloc استفاده کنید، زیرا آنها جداسازی بهتری بین منطق و نمایش فراهم می‌کنند.

مثال FutureBuilder با بارگذاری داده از شبکه

بیایید یک مثال عملی از FutureBuilder برای بارگذاری لیست کاربران از REST API را بررسی کنیم. کد مدیریت صحیح هر سه وضعیت AsyncSnapshot را نشان می‌دهد: بارگذاری، خطا و داده‌های آماده.

dart
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 را چندین بار فراخوانی می‌کند؟

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 با StreamBuilder چیست؟

FutureBuilder برای عملیات‌های ناهمگام یک‌باره طراحی شده است (یک درخواست HTTP، یک خواندن از پایگاه داده). StreamBuilder با جریان‌های داده کار می‌کند که می‌توانند مقادیر متعددی در طول زمان منتشر کنند (چت، به‌روزرسانی قیمت، موقعیت جغرافیایی). StreamBuilder از ConnectionState.active برای داده‌های جزئی پشتیبانی می‌کند، در حالی که FutureBuilder فقط waiting و done را پشتیبانی می‌کند.

چگونه از FutureBuilder با چند Future استفاده کنیم؟

برای چند Future موازی از Future.wait استفاده کنید و نتیجه را به یک FutureBuilder منتقل کنید. Future.wait لیستی از Futureها را دریافت می‌کند و Future<List> برمی‌گرداند — هنگامی که همه Futureها تکمیل شدند، builder آرایه‌ای از نتایج را دریافت می‌کند. برای درخواست‌های ترتیبی از زنجیره Future.then در یک Future یا FutureBuilderهای تودرتو (کمتر خوانا) استفاده کنید. جایگزین — بسته riverpod با AsyncValue برای حالت‌های ناهمگام متعدد.

چگونه Future را هنگام خروج از صفحه لغو کنیم؟

FutureBuilder Future را به طور خودکار لغو نمی‌کند. برای لغو از CancelableOperation از بسته async یا مکانیزم خود از طریق پرچم cancelled در State استفاده کنید. در dispose() پرچم را تنظیم کنید و پس از تکمیل Future قبل از فراخوانی setState آن را بررسی کنید. جایگزین، از بسته riverpod با AutoDispose استفاده کنید که به طور خودکار عملیات‌های ناهمگام را هنگام خروج از صفحه لغو می‌کند.

خلاصه

  • FutureBuilder — ویجت Flutter برای ساخت اعلامی UI بر اساس وضعیت Future از طریق AsyncSnapshot (waiting, done, error)
  • AsyncSnapshot — ظرف حاوی connectionState, data و error; برای مدیریت صحیح همه وضعیت‌های عملیات ناهمگام ضروری است
  • builder — callback با سه شاخه: hasError (نمایش خطا), hasData (نمایش داده), default (نشانگر بارگذاری)
  • FutureBuilder در مقابل setState — FutureBuilder برای یک عملیات ساده‌تر است، setState با Bloc/Riverpod برای منطق پیچیده با درخواست‌های متعدد بهتر است
  • جلوگیری از درخواست‌های تکراری — Future باید فیلد State باشد، آن را در متد build ایجاد نکنید تا از راه‌اندازی مجدد در هر بازسازی جلوگیری شود
  • لغو Future — FutureBuilder Future را در dispose لغو نمی‌کند; از CancelableOperation یا پرچم لغو برای جلوگیری از setState پس از نابودی استفاده کنید
  • Futureهای متعدد — برای درخواست‌های موازی از Future.wait با یک FutureBuilder استفاده کنید; برای ترتیبی — زنجیره‌ها در یک Future

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید