۵ راهکار برای بهبود عملکرد و performance فلاتر
زمان مطالعه: 6 دقیقه
۱۴۰۲/۶/۲۷

۵ راهکار برای بهبود عملکرد و performance فلاتر

در این مقاله به راهکار‌ها و نکاتی اشاره خواهد شد که با رعایت آنها اپلیکیشن توسعه داده شده با فلاتر عملکردی سریع تر و بهینه تری خواهد داشت. به این نکته توجه داشته باشید رعایت این موارد نیازمند شرایطی خاص خود هست که در هر بخش توضیح داده شده.

قبل از شروع نکات لازم به ذکر است که آشنایی کامل با زبان دارت و خواص آن در فرآیند توسعه شما با فریمورک فلاتر تاثیر زیادی در بهینه کدنویسی شما دارد پس از نکته غافل نشوید. همچنین به تاریخ انتشار و آخرین آپدیت مقاله دقت داشته باشید چرا که ممکن است برخی از این موارد در ورژن های بعدی فلاتر تغییر کنند.

1- استفاده از for  یاwhile  بجای forEach  و map

اگرچه کار با forEach  و یا map کردن داده ها بسیار سطح بالاتر و راحت بنظر میرسد اما در کار با داده های حجیم استفاده از for و یا while  سرعت بیشتری دارند. در فرآیند های معمول و داده های کم حجم بهینه ترین روش همان استفاده از forEach و map  خواهد بود چراکه کد های خوانایی بیشتری خواهند داشت اما در حجم داده های زیاد این مورد براحتی مشهود و قابل تست است.

کافیست که با استفاده از  متد stopwatch() زمان اجرا در حالت های مختلف اندازه‌گیری کنید:

void main() {
  final stopwatch = Stopwatch()..start();
  getDataFunction();
  stopwatch.stop();
  print('Function Execution Time : ${stopwatch.elapsed}');
}

در نمودار زیر میتوانید زمان اجرای برنامه با استفاده از متد های مختلف را ببینید:

مقایسه زمان اجرا

بطور خلاصه دلایل وجود این اختلاف در زمان اجرا بدلیل طبیعت functional programming  متدهای map  و forEach  دارای توابع objective داخلی برای کنترل تکرار بوده که نیازمند منابع پردازش بیشتر نسبت به for و while  هستند که در متد های for  وwhile  بطور مستقیم اتفاق میافتد. یا در فرآیند mapping به ازای هر element  یک لیست یا collection  بطور معمول ایجاد میشود که نیازمند تخصیص memory  در سیستم است.

2- آیکون ها و یا تصاویر اپلیکیشن را Precache  کنید.

در مواردی که از ثابت بودن و عدم تغییر تصاویر و یا ایکون ها اطمینان دارید، آنها را با استفاده از متد های زیر precache کنید.

  • برای تصاویر بدون نیاز به اضافه کردن پکیج:

precacheImage(AssetImage(imagePath), context);
  • و برای ایکون های svg با استفاده از پکیج flutter_svg:

precachePicture(ExactAssetPicture(SvgPicture.svgStringDecoderBuilder, iconPath),context,);

۳- lazy loading

بیشتر توسعه دهندگان فلاتر برای افزایش سرعت load  لیست ها و یا grid در داخل اپلیکیشن بجای map از متد builder استفاده میکنند درصورتی که اگر حجم داده ها از حدی بیشتر شود builder هم جوابگو نیست و نرم افزار با افت فریم یا لگ مواجه میشود؛ در این مواردgridview یا list را با استفاده همان builder  پیاده سازی کنید اما این بار تنها داده هایی را که کاربر میبیند را render کنید و با هر بار اسکرول کاربر به انتهای صفحه در صورت وجود داده‌ی بیشتر برای نمایش، مابقی لیست با grid را بارگذاری کنید. مانند مثال زیر:

  • ایجاد یک تابع برای شبیه سازی دریافت داده از سمت سرور

class _ItemFetcher {
  final _count = 103;  
  final _itemsPerPage = 5;
  int _currentPage = 0;

  // این تابع برای شبیه سازی گرفتن داده ها از سرور ساخته شده
  Future<List<WordPair>> fetch() async {
    final list = <WordPair>[];
    final n = min(_itemsPerPage, count - currentPage * _itemsPerPage);
    await Future.delayed(Duration(seconds: 1), () {
      for (int i = 0; i < n; i++) {
        list.add(WordPair.random());
      }
    });
    _currentPage++;
    return list;
  }
}
  • ساخت اسکرین لیست و بارگذاری داده‌های بعدی

class ListScreen extends StatefulWidget {
  @override
  ListScreenState createState() => ListScreenState();
}

class _ListScreenState extends State<ListScreen> {
  final _pairList = <WordPair>[];
  final itemFetcher = ItemFetcher();

  bool _isLoading = true;
  bool _hasMore = true;

  @override
  void initState() {
    super.initState();
    _isLoading = true;
    _hasMore = true;
    _loadMore();
  }

  // تابع اضافه کردن داده های بیشتر به لیست درصورت وجود
  void _loadMore() {
    _isLoading = true;
    _itemFetcher.fetch().then((List<WordPair> fetchedList) {
      if (fetchedList.isEmpty) {
        setState(() {
          _isLoading = false;
          _hasMore = false;
        });
      } else {
        setState(() {
          _isLoading = false;
          _pairList.addAll(fetchedList);
        });
      }
    });
  }

// ویجیت لیست داده ها
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      // نیاز به نمایش اسپینر در صورت وجود داده ی بیشتر
      itemCount: hasMore ? pairList.length + 1 : _pairList.length,
      itemBuilder: (BuildContext context, int index) {
        // بررسی داده های داخل لیست
        if (index >= _pairList.length) {
          // جلوگیری
          if (!_isLoading) {
            //   بار گزاری داده های بیشتر
            _loadMore();
          }
          // ویجیت اسپینر
          return Center(
            child: SizedBox(
              child: CircularProgressIndicator(),
              height: 24,
              width: 24,
            ),
          );
        }
        // ویجیت لیست
        return ListTile(
          leading: Text(index.toString()),
          title: Text(_pairList[index].asPascalCase),
        );
      },
    );
  }
}
پیش نمایش اپلیکیشن

4- پرهیز از rebuild کردن ویجت ها: 

ویجت های stateful هر بار با تغییر هر state مجدد ساخته میشوند. در نتیجه سعی کرده ویجت هایی که در صورت تغییر state وضعیت آنها تغییر نمی‌کنند را از آنها ایزوله کنید مخصوصا در استفاده از state management های مختلف. اگر چه ممکن است در استفاده از برخی state management  ها از ویجت stateful  استفاده نکنید اما باز همچنان بازسازی مجدد در صورت تغییر sate   اتفاق می‌افتد.

۵ – ویجت های قابل مشاهده

تنها ویجت هایی که کاربر آنها را میبیند را render کنید. در برخی موارد ممکن است با توجه به طراحی محصول دو ویجت متفاوت را در یک صفحه داشته باشید که باتوجه به شرایط مختلف هر بار یکی از آنها را نمایش دهید. در چنین حالتی دو ویجت را از ویجت مادر کاملا جدا کنید و با توجه به شرط موجود ویجتی را که باید نمایش داده شود را به ویجت مادر برگردانید. پیاده سازی این روش بسته به معماری های مختلف مورد استفاده در فلاتر متفاوت است اما این نکته را به یاد داشته باشید که هر ویجتی که داخل ویجت مادر باشد حتی درصورت عدم نمایش به کاربر بصورت کامل render میشود پس بهتر است که در همان مرحله‌ی اول در ساختار اصلی قرار نگیرد.

 

ممنون که تا اینجای مقاله همراه بودید. لطفا مباحث مورد نیاز خودتون رو در بخش نظرات وارد کنید تا در مقالات بعدی به اونها بپردازیم.

پروفایل پویا معروفی

نویسنده مقاله

کارآفرین حوزه‌ی پزشکی، توسعه دهنده موبایل و طراح محصول - هم‌بنیان گذار و مدیر عامل استارت آپ طب یاد - هم‌بنیان گذار و مدیر محصول مرکز مراقبت پزشکی، پرستاری در منزل سوژین - عضو انجمن صنفی رایانه‌ای حضور در پروژه های متعدد داخلی ‌و خارجی بعنوان توسعه دهنده موبایل و طراح محصول - حضور در پروژه های متعدد علوم پزشکی بعنوان توسعه دهنده موبایل

دیدگاه ها و پرسش ها