فلاتر

آموزشی Isolate در فلاتر و برنامه نویسی Multi Thread + فیلم

اپلیکیشن های فلاتر ممکن است در بعضی موارد نیاز به انجام پردازش های سنگین داشته باشند که این کار باعث میشود کاربر در هنگام استفاده از برنامه با مشکلات مختلفی روبرو شود.

برای حل این مشکل در فلاتر از مفهومی به نام Isolate استفاده میکنیم. برای کار با این مورد نیاز به بررسی یک سری موارد از قبل داریم.

در نظر داشته باشید که به طور کلی مبحث برنامه نویسی Multi Thread جزو مباحث پیشرفته در آموزش برنامه نویسی موبایل میباشد و اگر هنوز به مبانی ابتدایی تسلط ندارید شاید این مفاهیم برای شما پیچیده باشد.

در برنامه نویسی کامپیوتر، یک thread یا نخ یک واحد اجرای مستقل است که می تواند در یک برنامه اجرا شود.

هر thread دارای حافظه و شمارنده برنامه خود است. این به این معنی است که هر نخ می تواند داده های خود را داشته باشد و بدون اینکه بر نخ های دیگر تأثیر بگذارد، کار خود را انجام دهد.

threadها می توانند مزایای زیر را برای برنامه ها به ارمغان بیاورند:

  • بهبود عملکرد: نخ ها می توانند عملکرد برنامه را بهبود بخشند زیرا می توانند چندین کار را به طور همزمان انجام دهند.
    به عنوان مثال، اگر یک برنامه باید یک فایل را از اینترنت دانلود کند و در عین حال یک رابط کاربری گرافیکی را نیز اجرا کند، می توان این دو کار را در دو thread جداگانه اجرا کرد. این به این معنی است که دانلود فایل بر عملکرد رابط کاربری گرافیکی تأثیر نمی گذارد.
  • بهبود کارایی: نخ ها می توانند به بهبود کارایی برنامه کمک کنند زیرا می توانند عملیات را در چندین نخ جداگانه اجرا کنند.
    به عنوان مثال، اگر یک برنامه باید روی یک مجموعه داده بزرگ عملیاتی را انجام دهد، می توان این عملیات را در چندین thread جداگانه اجرا کرد. این می تواند زمان لازم برای انجام این عملیات را کاهش دهد.

با این حال، نخ ها می توانند خطرات زیر را نیز برای برنامه ها به همراه داشته باشند:

  • خطاهای همگام سازی: اگر نخ ها به درستی با یکدیگر هماهنگ نباشند، می توانند منجر به خطاهای همگام سازی شوند. خطاهای همگام سازی زمانی رخ می دهد که دو یا چند thread سعی می کنند به یک داده مشترک دسترسی پیدا کنند یا آن را تغییر دهند.
  • رقابت: نخ ها می توانند با یکدیگر رقابت کنند تا منابع سیستم را به دست آورند. این رقابت می تواند منجر به کاهش عملکرد شود.

برنامه نویسان باید قبل از استفاده از نخ ها، خطرات و مزایای آن را درک کنند.

در اینجا چند نمونه از کاربردهای thread ها آورده شده است:

  • پردازش چند رسانه ای، مانند پخش ویدیو یا پخش صدا
  • پردازش داده ها، مانند پردازش داده های مالی یا تحلیل داده های علمی
  • بازی های ویدئویی
  • برنامه های کاربردی وب

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

برنامه نویسی چند نخی (Multithreading) یک تکنیک برنامه نویسی است که به برنامه نویسان این امکان را می دهد تا چندین کار را به طور همزمان در یک برنامه اجرا کنند. هر کار در یک نخ جداگانه اجرا می شود.

برنامه نویسان می‌توانند با استفاده از multi thread، برنامه‌هایی بنویسند که در حالت موازی چندین عملیات را انجام می‌دهند، که می‌تواند به سرعت اجرای بهتر و بهتر برنامه را به شکلی که کاربر بهترین تجربه را دریافت می‌کند به شکلی که کاربر بهترین تجربه را دریافت می‌کند، کمک کند.

تقریبا هر نرم افزاری که نیاز به انجام پردازش های مختلف به شکل موازی باشد از این تکنیک استفاده میکند.

برای مثال در یک مرورگر اینترنتی در هر تب میتوانید به شکل جداگانه فایل های مختلفی را دانلود کنید.

در واقع هر فرآیند یا Process میتواند چندین Thread را ایجاد کند که هرکدام قطعه کد و یا دستور خاصی را اجرا میکنند. بدین ترتیب شاهد این خواهیم بود که برنامه ها با سرعت بیشتری در کامپیوترها اجرا میشوند.

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

اگر فرآیند دیگری نیاز به اجرا داشته باشد، باید منتظر نوبت خود باشد. در مورد multi thread، چندین Thread به طور نسبی به طور همزمان پردازش می‌شوند. اگرچه پردازش واقعاً همزمان اتفاق نمی‌افتد، اما در حال حاضر امکان‌پذیر است.

اما حتی “شبه همزمانی” نیز باعث افزایش عملکرد می‌شود. سیستم نخ‌ها را به گونه‌ای هوشمندانه سازماندهی و محاسبه می‌کند که کاربر آن را پردازش همزمان می‌پندارد.

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

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

زمانی که برنامه‌ی فلاتر اجرا می‌شود، یک main thread یا isolate برای برنامه‌ی شما ایجاد می‌شود که کدهای شما داخل اون thread یا isolate اجرا می‌شن که بهش main thread یا UI thread گفته میشود.

در واقع isolate همان Thread در سایر زبان‌ها هست که در زبان برنامه نویسی دارت به آن isolate میگویند.

بین isolate ها حافظه‌ی مشترکی وجود ندارد.

برای برقراری ارتباط بین isolate ها از port و message ها برای تبادل پیام استفاده میشود.

در برنامه‌های ساده‌ی فلاتر معمولاً یک isolate وجود دارد، اما درصورتی که قصد انجام عملیاتی طولانی و سنگین رو داشته باشید، برای اینکه عملکرد UI Thread مختل نشه، بهتر هست که برای انجام آن یک Isolate جدید ایجاد کنید.

برای اینکه بهتر مزیت استفاده از Isoalte در فلاتر را درک کنید با یک مثال این کار و انجام میدهیم.

ابتدا یک انیمیشن ایجاد میکنیم و داخل برنامه قرار میدهیم.

این انیمیشن یک ویجت Container را از سمت چپ صفحه به سمت راست حرکت میدهد و این کار تکرار میشود.

کدهای این بخش از انیمیشن به شکل زیر است.


class AnimatedContainer extends StatefulWidget {
  @override
  _AnimatedContainerState createState() => _AnimatedContainerState();
}

class _AnimatedContainerState extends State<AnimatedContainer> with SingleTickerProviderStateMixin  {

  late AnimationController _controller;
  late Animation<Offset> _animation;
  
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _controller = AnimationController(vsync: this,duration: Duration(seconds: 2));
    _animation = Tween<Offset>(begin: Offset.zero,end: Offset(6,0)).animate(_controller);
    _controller.repeat();
 }
 
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Container(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,

          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SlideTransition(position: _animation,
              child: Container(
                width: 50,
                height: 50,
                color: Colors.redAccent,
              ),),
              SizedBox(height: 40,),
              ElevatedButton(onPressed: ()async{
                   TestTask();
    
    },
    
    ],
          ),

        ),
      ),
    );
  }


}

در اینجا برای شبیه سازی یک عملیات پردازش سنگین متد TestTask را هنگام کلیک کردن روی دکمه فراخوانی میکنیم.

این متد یک حلقه بسیار طولانی است که انجام آن نیاز به منابع زیادی دارد.

Future<int> TestTask()async{
  var result = 0;
  for(int i = 0; i<1450000000;i++){
    result++;
  }
  return result;

}

در تصویر زیر مشاهده میکنید که زمان فراخوانی این متد انیمیشن مورد نظر دچار مشکل میشود و در صفحه ثابت میماند تا عملیات متد TestTask تکمیل شود.

علت این مورد این است که هر دو کار در حال پردازش در Isolate اصلی برنامه است و رابط کاربری با مشکل روبرو میشود.

الگوی طراحی Singleton

برای حل این مشکل باید عملیات هایی که پردازشی سنگینی نیاز دارند را در یک Isolate دیگر قرار دهیم.

حالا مثال و قبلی با استفاده از Isolate بررسی میکنیم.

کدهای زیر را در نظر بگیرید.

Future<int> TestTask(SendPort sendPort)async{
  var result = 0;
  for(int i = 0; i<1450000000;i++){
    result++;
  }
 sendPort.send('Result: $result');
  return result;

}

ابتدا به متدی که داشتیم یک پارامتر ورودی از کلاس SendPort اضافه میکنیم.

همانطور که گفتیم راه ارتباطی بین Isolateها در فلاتر از طریق ارسال پیام میباشد. در صورتی که بخواهید به یک Isolate دیگر پیامی ارسال کنید از SendPort کمک میگیریم.

در اینجا نیز نتیجه نهایی پردازش را از همین طریق به Isolate اصلی برنامه ارسال میکنیم.

کدهای رویداد کلیک دکمه داخل صفحه را هم به شکل زیر تغییر میدهیم.

 var rec_port  = ReceivePort();

              var isolates =  await Isolate.spawn(TestTask,rec_port.sendPort);
              rec_port.listen((message) { 
                print("Message: $message");
              });

ابتدا یک ReceivePort تعریف میکنیم تا بتوانیم پیام هایی که از طریق Isolate جدید ارسال میشود را دریافت کنیم.

برای ساخت Isolate جدید هم از متد Isolate.spawn استفاده میکنیم.

پارامتر اول این متد همان تابع پیاده سازی شده است که میخواهیم در یک Thread جدید قرار گیرد و پارامتر دوم هم در واقع آرگومان های مورد نیاز تابع TestTask میباشد که از همان ReceivePort مقدار SendPort را قرار داده ایم.

در نهایت هم برای اینکه بتوانیم پیام های ارسالی را دریافت کنیم برای ReceivePort یک Listener تعریف میکنیم که از نوع استریم است.

با اجرای این کد بدین شکل مشاهده میکنید که دیگر انیمیشنی که در رابط کاربری اپلیکیشن فلاتر وجود دارد دچار مشکل نمیشود و به شکل همزمان نیز عملیات پردازش انجام میشود.

در صورتی که میخواهید به شکل حرفه ای طراحی اپلیکیشن را یاد بگیرید میتوانید از دوره آموزش فلاتر پروژه محور استفاده نمایید.

Hesam

Recent Posts

گیتهاب اکشن چیست؟ آموزش استفاده از گیتهاب اکشن در برنامه نویسی فلاتر

گیتهاب اکشن GitHub Actions یکی از ابزارهای گیتهاب است که به شما کمک می‌کنه تا…

7 روز ago

آموزش افزایش سرعت اجرای وب اپلیکیشن های فلاتر

اگر یک برنامه نویس فلاتر هستید و با از نسخه وب اپلیکیشن پروژتون استفاده میکنید…

1 ماه ago

آموزش جامع انتشار اپلیکیشن اندروید و فلاتر در فروشگاه گوگل پلی Google play

به عنوان یک برنامه نویس فلاتر یا اندروید بعد از اتمام پروسه طراحی اپلیکیشن نیاز…

2 ماه ago

دانلود سورس کد رابط کاربری اپلیکیشن فلاتر پروژه پادکست

طراحی رابط کاربری اپلیکیشن پادکست خود را با استفاده از این کیت توسعه UI/UX فلاتر…

2 ماه ago

فایربیس چیست؟ معرفی سرویس ابری Firebase و کاربردهای آن

فایربیس، پلتفرمی قدرتمند از شرکت گوگل برای توسعه و مدیریت برنامه‌های موبایل و وب است.…

3 ماه ago

آموزش پیاده سازی Method Channel در فلاتر + فیلم

فلاتر یک فریم ورک برنامه نویسی چندسکویی است که این امکان را برای برنامه نویس…

3 ماه ago