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

  • مدرس : عماد قاسم پور
  • سطح آموزش : پیشرفته
  • مدت : 124 دقیقه
  • تعداد دانشجو : 1938

دوره Dart پیشرفته
اگر با دوره قبلی مربوط به Flutter یعنی آموزش جامع Flutter و زبان Dart از صفر در ویلرن همراه بودید با زبان Dart که ابزار کار با فریمورک Flutter هست آشنا هستید ( اگر قصد دارید کار با زبان Dart رو شروع کنید توصیه میکنیم اول دوره قبل در این مسیر رو بررسی کنید )
در دوره دارت پیشرفته ویژگی های زبان برنامه نویسی Dart رو به صورت کامل مورد بررسی قرار خواهیم داد تا ابزار کار خودمون در مسیر طراحی با فریمورک Flutter رو بهتر بشناسیم و بتونیم به خوبی ازش استفاده کنیم.

منظور از “پیشرفته” در زبان Dart چیه؟
وقتی واژه “Dart پیشرفته ” رو به کار میبریم یعنی ما مبانی زبان Dart رو که شامل تعریف متغیر – دستورات شرطی – حلقه ها – تعریف توابع میشه رو میدونیم و حالا میخوایم یه قدم جلوتر بریم و بیشتر این زبان برنامه نویسی رو بشناسیم

در دوره دارت پیشرفته چی یاد میگریم؟
توی این دوره ما ابتدا مباحث مختلفی مثل توابع Anonymous ،کار با نوع List ها و ویژگی های اون در زبان Dart ، مبحث ارث بری(Inheritance) و امکانات این زبان در این موضوع رو به طور کامل بررسی میکنیم و بعد وارد بحث برنامه نویسی asynchronous که خیلی هم مهم هست میشیم و به طور کامل راجع به Future ها , Stream ها استفاده از FutureBuilder و StreamBuilder و همچنین مفهوم و کاربرد async/await در زبان دارت صحبت میکنیم.

  • درس 1 : معرفی دوره آموزشی

    2 دقیقه
  • 11 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

    در این جلسه قصد داریم دستورات شرطی در زبان دارت رو بررسی کنیم.
    به طور مثال یک متغیر به نام databaseResult با مقدار data و یک متغیر با نام finalResult ایجاد می کنیم.

    void main() { var databaseResult = "data"; var finalResult; }

    حالا قصد داریم از طریق دستور شرطی if مقدار داخل databaseResult رو چک کنیم و در نهایت داخل finalResult قرار بدیم.

    void main() { var databaseResult = "data"; var finalResult; if(databaseResult!=null) { finalResult = databaseResult; } else { finalResult = "default"; } print(finalResult); }

    حالا در زبان dart این ساختار رو میتونیم به شکل دیگری پیاده سازی کنیم.

    void main() {
      var databaseResult = "data";
      var finalResult;
      finalResult = databaseResult ?? "default";
      print(finalResult);
    }

    یعنی اگر مقدار databaseResult برابر null نبود ، مقدار finalResult برابر data و در غیر این صورت مقدار finalResult برابر default خواهد بود.
    حالا فرض کنید قصد داریم یک مقدار روی از یک وب سرویس بخونیم و روی اون پردازش انجام بدیم اما نمیدونیم مقداری از سمت وب سرویس برگشته یا خیر.
    فرض کنید یک متغیر رشته ای به نام webResult با مقدار ok داریم.

    String webResult="ok";

    حالا بیایم همین مقداری که به طور مثال وب سرویس به ما برگردونده (ok) رو با حروف بزرگ چاپ کنیم.

    void main() {
      String webResult="ok";
      print(webResult.toUpperCase());
    }

    حالا اگر وب سرویس دیتا رو برنگردونه ، طبیعتا به ارور برمیخوریم. چرا؟ چون قصد داریم رو یک مقدار null یک عملیاتی انجام بدیم. حالا چطور میتونیم این مشکل رو حل کنیم؟
    فقط لازمه قبل از اینکه تابع رو فراخوانی کنیم ، یک ? و بعد از تابع ، به طور مثال toUpperCase رو فراخوانی کنم.
    یعنی اگر مقدار webResult مخالف null بود ، تابع toUpperCase فراخوانی بشه.

    void main() {
      String webResult="ok";
      print(webResult?.toUpperCase());
    }

    الان اگر برنامه رو اجرا کنیم ، عملیات toUpperCase انجام نمیشه و طبیعتا به ارور هم برنمیخوریم.

  • 10 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

    ما در Dart برای تعریف توابع ناشناس (Anonymous) بدین شکل عمل خواهیم کرد.

    void main() {
      var sayHello=() {
      }
    }

    برای تابع sayHello یک مقدار ورودی name نیز تعریف می کنیم.

    void main() {
      var sayHello=(String name) {
         return "Hello $name";
      }
    }

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

    void main() {
      var sayHello=(String name) {
         return "Hello $name";
      };
      print(sayHello("Student"));
      print(sayHello("Teacher"));
    }

    یک مثال کاربردی
    فرض کنید ما قصد داریم عبارتی که تابع sayHello برای ما نمایش میده رو به زبان های مختلف داشته باشیم.
    یک متغیر به نام greeting ایجاد میکنیم که همین متغیر greeting خودش یک تابع ناشناس (Anonymous) هست و یک پارامتر ورودی داره که ترجمه عبارت Hello هست.

    void main() {
      var greeting =(String helloTranslation) {
        return (String name) => "$helloTranslation $name";
      };
      var spanish=greeting("Hola");
      var french=greeting("Bonjour");
      var italian=greeting("Ciao");
    
      print(spanish("welearn"));
      print(french("welearn"));
      print(italian("welearn"));
    }

    همچنین ما میتونیم توابع ناشناس(Anonymous) رو به صورت Template نیز پیاده سازی کنیم.

    Function greeting(String helloTranslation) {
        return (String name) => "$helloTranslation $name";
    };

    بدین صورت ما به این تابع در همه جای برنامه دسترسی داریم.

  • 16 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

    بسیاری از Widget به عنوان پارامتر ورودی لیست دریافت می کنند. به طور مثال Row Widget , Column Widget , Stack Widget.
    نحوه تعریف لیست به شکل زیر است.

    void main() {
      var list = [1,3,7,4,6,9];
    }

    همچنین به طور مثال میتونیم اولین یا آخرین آیتم لیست رو از طریق توابع first و last نمایش دهیم.

    void main() {
      var list = [1,3,7,4,6,9];
      print(list.first);
      print(list.last);
    }

    یکی دیگر از پارمترهای مهم در List تابع where هست. حالا کارکرد این پارامتر چیه؟ فرض کنید قصد داریم آیتم های زوج این لیست بالا رو جدا و نمایش دهیم.

    void main() {
      var list = [1,3,7,4,6,9];
      print(list.where((var item) => item%2==0));
    }

    حالا اگر این دستور رو اجرا کنید ، مشاهده خواهید کرد که پارامتر بازگشتی تابع where خودش یک لیست هست.
    حالا یه تمرین باحال
    بیایم آیتم های لیست بالا رو دو برابر کنیم و تو یک لیست جدید ذخیره کنیم.
    روش اول
    میایم یک متغییر به نام doubledList ایجاد می کنیم. بعد یک لیست ایجاد و آیتم هایی که داخل لیست بالا هست رو از طریق یک حلقه دو برابر میکنیم.

    void main() {
      var list = [1,3,7,4,6,9];
      print(list.where((var item) => item%2==0));
      var doubledList=[for(var item in list) item*2];
      print(doubledList);
    }

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

    void main() {
      var list = [1,3,7,4,6,9];
      var doubledList2=list.map((var item) => item*2);
      print(doubledList2);
    }

    حالا اگر بخوایم لیست بالا رو به صورت رشته داشته باشم چیکار کنیم؟ از طریق متد toString

    void main() {
      var list = [1,3,7,4,6,9];
      var listString=list.map((var item) => item.toString());
      print(listString);
    }

    حالا مجموع آیتم های List رو چطور داشته باشیم؟
    تابع reduce
    تابع reduce میاد آیتم ها رو با توجه به تابعی که شما تعیین می کنید ، تبدیل به یک آیتم میکنه و در نهایت برمیگردونه.

    void main() {
      var list = [1,3,7,4,6,9];
      var sum=list.reduce((i, j) => i+j);
      print(sum);
    }

    آیتم هایی که میخوایم تبدیل کنیم i و j هست و آیتمی که میخوایم برگردونیم i+j هست. در نهایت جمع این مقادیر در کنسول 30 هست.
    حالا بیایم یک تابع دیگه رو هم بررسی کنیم.
    تابع fold
    تفاوت بین تابع reduce و fold در این هست که مقدار اولیه تابع reduce عدد 0 هست و مقدار اولیه تابع fold مقداریست که شما تعیین می کنید.
    به طور مثال داریم

    void main() {
      var list = [1,3,7,4,6,9];
      var sum2 = list.fold(initialValue, (prev, element) => prev + element);
    }

    nitialValue همان مقدار اولیه هست که شما میتونید تعیین کنید.

    void main() {
      var list = [1,3,7,4,6,9];
      var sum2 = list.fold(initialValue, (prev, element) => prev + element);
    }

    حالا مقداری که کنسول نمایش میده 35 هست.
    تا اینجا ما لیست هایی داشتیم که تمام آیتم های اون لیست شبیه به هم بودن (همه یا int بودن یا string)
    اما زبان Dart محدودیتی برای نوع آیتم ها در لیست مثل زبان های دیگه همچون جاوا ایجاد نمیکنه و شما میتونید در یک لیست انواع مختلفی از آیتم ها رو داشته باشیم. آیتم int ، آیتم string ، آیتم یک تایپ از یک کلاس و …

    void main() {
      var multiTypeList = [1,"a",2,"b",3];
    }

    حالا میتونیم روی این multiTypeList فیلترینگ انجام بدیم. یعنی به طور مثال بیایم فقط از اعداد این لیست استفاده کنیم. طبیعتا باید از تابع where برای اینکار استفاده کنیم.

    void main() {
      var multiTypeList = [1,"a",2,"b",3];
      var intList = multiTypeList.whereType();
      print(intList);
    }
  • 14 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

    حالا برای اینکه دیگر کلاس ها ملزم به اجرای قوانین کلاس engine باشند ، باید کلاس engine رو تبدیل به کلاس abstract کنیم.کلاس های abstract در زبان Dart ساختار رو مشخص می کنند ، اما پیاده سازی در داخل خودشون ندارند.
    حالا چیکار کنیم که کلاس های PetroEngine و DieselEngine از کلاس engine ارث بری کنند؟ فقط لازمه extend رو به هر دو کلاس اضافه کنیم.

    abstract class Engine {
    }
    class PetroEngine extend Engine {
    }
    class DieselEngine extend Engine {
    }

    دقت کنید که کلاس هایی (PetroEngine و DieselEngine) که از کلاس abstract ارث بری می کنند ، مجبور به اجرای توابع این کلاس هستند.
    حالا مقدار horsePower رو در کلاس engine در نظر میگیریم و بعد از اون تابع start رو تعریف می کنیم.

    abstract class Engine {
       int horsePower = 200;
       void start();
    }

    دقت کنید که پیاده سازی تابع start در این کلاس انجام نمیشه. در واقع کارخانه بیان میکنه ، من کار ندارم که این موتور با چه مکانیزمی قراره start بشه. اما کاری کنید دکمه start برای این کار وجود
    داشته باشه.
    حالا اگر این کدها رو در داخل اندروید استودیو نوشته باشید ، به شما دو خطا میده که مبنای اون دو خطا در این هست که میگه تابعی هست که باید override بشه.

    abstract class Engine {
       int horsePower = 200;
       void start();
    }
    class PetroEngine extend Engine {
        @override
        void start() {
            
        }
    }
    class DieselEngine extend Engine {
        @override
        void start() {
            
        }
    }

    هر کدام از این دو تابع در هر دو کلاس نحوه پیاده سازی خودشون رو دارند و طبیعتا نحوه پیاده سازی موتور دیزلی با بنزینی تفاوت داره ، اما باید از قوانینی که کلاس Engine برای اونها تعریف کرده پیروی کنند.

    abstract class Engine {
       int horsePower = 200;
       void start();
    }
    class PetroEngine extend Engine {
        @override
        void start() {
            print("Petro Engine Started...");
        }
    }
    class DieselEngine extend Engine {
        @override
        void start() {
            print("Diesel Engine Started...");
        }
    }

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

    class Platform extend PetroEngine {
        @override
        void start() {
            super.start();
            print("Cooling System Working...");
        }
    }

    حالا در قدم آخر یک کلاس برای یک خودرو ایجاد میکنیم و مقدار horsePower این خودرو رو افزایش می دهیم.

    class AudiR8 extend Platform {
        AudiR8 start() {
            super.horsePower=300;
            print(super.horsePower);
        }
    }
  • 19 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

    در این قسمت قصد داریم به خودرویی که اضافه کردیم یک سری ماژول اضافه کنیم. کارخانه همه ماژول ها رو خودش تولید نمیکنه. به طور مثال کارخانه صندلی خودرو رو از یک تولید کننده دیگه دریافت میکنه. در نتیجه یک کلاس به نام Seat ایجاد میکنیم.

    class Seat {
        void configSeat() {
    	print("Seat Configured By Factory");
        }
    }

    حالا قصد داریم این صندلی رو در خودرو AudiR8 ست کنیم.

    
    class AudiR8 extend Platform implements Seat {
        AudiR8 start() {
            super.horsePower=300;
            print(super.horsePower);
        }
        @override
        void configSeat() {
          print("Seat Configured By Driver")
        }
    }
  • 12 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

    در این جلسه قصد داریم در مورد برنامه نویسی آسنکرون در زبان برنامه نویسی Dart صحبت کنیم که بسیار پرکاربرد هم هست. به طور مثال شما قصد دارید یک ساختار رو از یک وب سایت دریافت کنید یا یک آیتم رو در یک بخش از دیتابیس ذخیره کنید. تمام این موارد از طریق برنامه نویسی آسنکرون انجام میشه.
    حالا اولین قدم ، استفاده از Future در زبان برنامه نویسی Dart هست.
    بیایم یک مثال باحال بزنیم…
    فرض کنید شما قصد دانلود یک عکس رو دارید؟ میاید به فلاتر میگید میشه این عکس رو برام دانلود کنی؟ فلاتر میگه باشه ، این جعبه رو بگیر بزار اونجا… ولی جعبه رو بازش نکن تا وقتی بهت گفتم… شما هم گوش به فرمان منتظر دستور فلاتر… حالا در این بین ممکنه یه اکشن رخ بده یا یوزر وارد یک تب دیگه بشه. پس از اون فلاتر یک دیتا رو داخل جعبه میزاره و به شما میگه حالا میتونی این جعبه رو باز کنی ;):)

    شما اون جعبه رو باز میکنی. ممکنه دیتایی که شما میخواین باشه یا یک ارور
    این ساختار Future هست.
    پس Future سه حالت دارند.
    1- uncomplete هستن و منتظریم کی چه زمانی کامل میشن.
    2- کامل شدن و یک دیتا در داخل آن هست.
    3- کامل شدن و اما یک ارور داخل آن است.

    حالا بیایم یک Future تعریف کنیم.
    استفاده از Future.value
    یک متغیر تعریف و نام آن رو result در نظر میگیریم. میتونیم یک Future تعریف کنیم که یک دیتا برگردونه یا یک خطا. الان یک دیتا رو میخوایم برگردونه.

    
    void main() {
        var result=Future.value(2);
        result.then((value)=>print(value));
    }

    حالا باید گوش بدیم که چه زمانی دیتا از Future برای ما برمیگرده. برای اینکار از تابع then استفاده می کنیم. صبر میکنیم اون دیتا در value قرار بگیره تا اون پردازشی که قصد داریم رو روش انجام بدیم.
    حالا میایم یک print تعریف میکنیم.

    
        print("Welearn");
    }

    پس از run برنامه ، اول Welearn تایپ میشه و بعد از اون دیتا ما.
    استفاده از Future.error
    شما میتونید از طریق Future یک خطا هم برگردونین.

    
    void main() {
        var result=Future.error(Exception("Error"));
        result.then((value)=>print(value));
    }

    استفاده از Future.delayed
    Future.delayed میاد یک مدتی صبر میکنه و بعد یک عملیاتی (دیتا – ارور) رو برمیگردونه.

    
    var result=Future.delayed(Duration(seconds:3),()=>Exception("Web Error"));
    

    به طور مثال 3 ثانیه صبر کن و بعد به عنوان پارامتر دوم دیتایی که میخواد برگردونه رو بهش نسبت میدیم.

    
    void main() {
         var result=Future.delayed(Duration(seconds:3),()=>Exception("Web Result"));   
         result.then((value)=>print(value));
         print("Welearn");
    }

    پس از اجرای برنامه ، Welearn چاپ و پس از 3 ثانیه دیتا Web Result نمایش داده میشه.
    حالا اگر به جای اینکه دیتا برگرده Exception به صورت Web Error برگشت ، چطور ارور رو دریافت کنیم؟
    میتونیم از catchError استفاده کنیم. این برای ارور Future استفاده میشه.

    
    void main() {
        var result=Future.delayed(Duration(seconds:3),()=>Exception("Web Error"));
        result.then((value)=>print(value));
        .catchError((value)=>priny(value)).whenComplete(()=>print("Job Done");
        print("Welearn");
    }
  • 8 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

    در این قسمت قصد داریم Future رو در ساختار UI پیاده سازی کنیم.فلاتر اومده یک Widget اختصاصی مخصوص Future استفاده کرده به نام Future Builder.برای استفاده از Future Builder در مرحله اول ، باید یک اپلیکیشن ایجاد کنیم.
    1- کتابخانه Material رو به پروژه اضافه می کنیم.

    
    import 'package:flutter/material.dart';

    2- یک Widget به صورت Stateless ایجاد میکنیم و ساختار پایه اپلیکیشن رو پیاده سازی می کنیم.

    
    import 'package:flutter/material.dart';
    void main() {
         runApp(App());
    }
    class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return MaterialApp(
           home: Scaffold (
            appBar: AppBar(),
            body: Container (
             child: Center (
              
             ),
            ),
           ),
         ),
       }
     }
    

    حالا میایم به child مربوط به Center ویجت Future Builder رو نسبت میدیم. Future Builder چندین آیتم داره.
    1- آیتم Future
    2- آیتم initialData مقدار اولیه Future تا قبل اینکه دیتا از سمت سرور برگرده (به طور مثال میتونید یک ساختار لودینگ در این آیتم ایجاد کنید)
    3- آیتم Builder نحوه عملکرد Future براساس دیتایی که از سمت Future Builder

    
    import 'package:flutter/material.dart';
    void main() {
         runApp(App());
    }
    class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return MaterialApp(
           home: Scaffold (
            appBar: AppBar(),
            body: Container (
             child: Center (
              child: FutureBuilder (
               initialData: "Wait...",
               future: Future.delayed(Duration(seconds: 2),()=>"Hello World"),
               builder: (context,snapShot) {
                if(snapShot.hastData) {
                 return Text(snapShot.data as String);
                }
                 else if(snapShot.hasError) {
                 return Text(snapShot.error as String);
                }
               },
              ),
             ),
            ),
           ),
         ),
       }
     }
    
  • 12 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

    اگر با کامپیوتر و به خصوص اینترنت سروکار داشته باشید به احتمال زیاد لغت Stream به گوشتان خورده است. اگر هم نخورده است نگران نباشید خوب الان دیگر آن را شنیده اید. تا به حال به این موضوع دقت کرده اید که برای گوش کردن یک فایل صوتی آن را روی کامپیوتر یا پلیر خود کپی میکنید و سپس آن را پخش میکنید.
    اما هنگامی که به رادیوی اینترنتی گوش میکنید مجبور نیستید که اول تمام رادیو را روی کامپیوتر خود کپی کنید و سپس آن را گوش کنید. اطلاعات همان طور که به کامپیوتر شما میرسند فورا اجرا میشوند. این باعث میشود که شما بتوانید به صورت آنلاین صوت و ویدئو را تماشا کنید. به این کار Streaming میگویند.

    وقتی یک مجموعه ای از دیتا در یک بازه زمانی میخواد برگرده و ما نمیدونیم این مجموعه دیتا چقدر ممکنه طول بکشه و چه Value داشته باشه ، در این اینجا دیگه Future برای ما کارایی نداره و باید بریم سراغ Stream

    استفاده از Stream
    برای استفاده از Stream باید کلاسی داشته باشیم که اون Stream رو برای شما فراهم کند.
    در اینجا اومدیم یک کلاس IntegerStream رو ایجاد کردیم که این کلاس هر ثانیه 1 عدد رو به صورت افزایشی برای ما فراهم میکنه.

    
    import 'dart:async';
    
    class IntegerStream{
      var _count=1;
      final _controller=StreamController<int>();
    
      Stream<int> get stream => _controller.stream;
      IntegerStream(){
        Timer.periodic(Duration(seconds: 1), (value){
          _controller.sink.add(_count);
          _count++;
        });
      }
    }
    

    حالا میایم از همین کلاس برای استریم استفاده میکنیم. حالا کلاس با یک stream به ما میده که داخل آن یک Value با مقدار int هست.
    حالا استریم رو داریم و باید بهش گوش بدیم.

    
    import 'package:welearndartadvanced/streams/integer_stream.dart';
    
    void main() {
      IntegerStream().stream.where((event) => event%2==1).map((event) => "stream value is $event").listen((event) {
        print(event);
      }, onError: (error) => print("error"), onDone: () => print("done"));
    }
    

    برای گوش دادن در بحث Future ما از تابع then استفاده می کردیم و در بحث Stream از تابع listen استفاده می کنیم.

    
    void main() {
      IntegerStream().stream.listen((event) {
        print(event);
     });
    }
    

    در کد بالا پس از Run برنامه میبینید که در کنسول از مقدار 1 شروع و به بالا چاپ می شود.
    حالا این استریم علاوه بر اینکه دیتا رو برمیگردونه ، یک سری اطلاعات دیگر هم ارائه میده همچون خطا

    
    import 'package:welearndartadvanced/streams/integer_stream.dart';
    
    void main() {
      IntegerStream().stream.where((event) {
        print(event);
      }, onError: (error) => print("error"), onDone: () => print("done"));
    }
    

    به این طریق میتونید دیتا ، پیغام خطا و اتمام یک Stream رو دریافت کنید.
    اما یک نکته باحال :
    اگر یادتون باشه ما در List میتونستیم از فیلترها استفاده کنیم. به طور مثال فقط آیتم های زوج رو از لیست استخراج کنیم. دقیقا همین روندها رو میتونیم با Stream هم انجام بدیم. یعنی به طور مثال کاری کنیم Stream فقط آیتم های زوج رو برگردونه و بیخیال آیتم های فرد بشه. چطور اینکار رو انجام بدیم؟

    استفاده از تابع where

    
    import 'package:welearndartadvanced/streams/integer_stream.dart';
    
    void main() {
      IntegerStream().stream.where((event) => event%2==1).listen((event) {
        print(event);
      }, onError: (error) => print("error"), onDone: () => print("done"));
    }
    

    حتی میتونیم از طریق تابع Map آیتم ها رو تغییر هم بدیم. به طور مثال یک رشته رو به همراه عدد برگردونیم.

    
    import 'package:welearndartadvanced/streams/integer_stream.dart';
    
    void main() {
      IntegerStream().stream.where((event) => event%2==1).map((event) => "Stream Value Is $event").listen((event) {
        print(event);
      }, onError: (error) => print("error"), onDone: () => print("done"));
    }
    

    همچنین میتونید از طریق پکیج async دارت به امکانات بیشتری در خصوص Future و Stream دسترسی داشته باشید.

  • 4 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

  • 12 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

  • 0 دقیقه

    برای مشاهده ویدئوی این درس می بایست در دوره ثبت نام نمائید.

نظرات دوره آموزش مجازی جامع و پیشرفته زبان Dart

  • برای مشاهده نظرات و سوالات، بر روی دکمه مربوطه کلیک کنید
  • قابلیت ارسال نظرات به صورت متنی، صوتی، تصویری
1.9K
0
افکار شما را دوست دارم، لطفا نظر دهیدx