آموزش فلاتر ( Flutter ) - ارتباط با سرور Dio

https://files.virgool.io/upload/users/35634/posts/oljoppi6tbvw/zwpemtw9rrtj.png چند وقتی میشه با فلاتر آشنا شدم. نسبت به تجربه‌ای که تو اندروید داشتم طراحی UI تو فلاتر خیلی آسون‌تره واسه همین تصمیم گرفتم یه پروژه با فلاتر درست کنم و تصمیم دارم پروژمو این جا با شما به اشتراک بزارم. تو این مجموعه از پست‌ها چند تا از مهم‌ترین موضوعات فلاتر رو باهم بررسی می‌کنیم و در نهایت یک پروژه کامل رو به پایان می‌رسونیم. این پست چهارمین پست از این سری هستش و در اون به ارتباط با سرور با استفاده کتابخونه Dio می‌پردازیم. برای دیدن قسمت قبل می‌تونید به این لینک مراجعه کنید.مطالبی که تو این مجموعه یاد می‌گیریم به چند قسمت تقسیم میشن:مقدمه.طراحی UI اولیه اپلیکیشن.ساخت مدل‌ها و کدهای مربوط به تبدیل اون به Json (از کتابخونه معروف json_serializable استفاده می‌کنیم).ارتباط با سرور (از کتابخونه Dio تو این قسمت استفاده شده).استفاده از کتابخونه cached_network_image برای گرفتن عکس از اینترنت و کش کردن اون.استفاده از انیمیشن در فلاتر.ساخت launcher icon دلخواه برای android و ios در فلاتر.ساخت سرور فیکخوب قبل از این که یه راست بریم سراغ کتابخونه Dio باید یه سرور داشته باشیم که بتونیم داده‌هارو از روی اون بخونیم. تو این اپ ما از سرور فیک JSONPlaceholder استفاده کردیم. این سایت به ما این امکان رو میده که از API ها از پیش آماده شدش استفاده کنیم، علاوه بر اون با استفاده از یک فایل Json این امکان رو به ما میده که سرور API فیک خودمون رو هم بسازیم. از طریق این لینک می‌تونید به قسمتی برید که آموزش میده سرور فیک خودتون رو بسازید. در این پروژه هم از این فایل json به عنوان منبع سرور فیک استفاده شده. بیشتر از این توضیحی نمیدیم و میریم سر اصل مطلب. اگر خواستید می‌تونید دایکیومنت‌های سایت رو بررسی کنید و سرورفیک خودتون رو بسازید.کتابخانه Dioکتابخانه Dio قابلیت‌های زیادی از جمله پشتیبانی از Interceptor ها، تنظیمات(پیکربندی) سراسری، کنسل کردن درخواست‌ها، دانلود فایل‌ها و ... داره. توضیحات خود کتابخونه Dio:A powerful Http client for Dart, which supports Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout etc.واسه استفاده از این کتابخونه اول باید اون رو به پروژه اضافه کنید. پس کد زیر رو به فایل pubspec.yaml اضافه کنید.dependencies: dio: 3.x.x #latest versionدستور flutter pub get رو اجرا کنید و دیگه همه چیز آمادس.متدهای GET , POST , PUT , DELETEمتد GETکد زیر یک نمونه ساده از دریافت داده با استفاده از متد GET هستش.import 'package:dio/dio.dart'; void getHttp() async { try { Dio dio= Dio(); Response response = await dio.get(&quothttp://www.google.com&quot); print(response); } catch (e) { print(e) } }در کد بالا یه در خواست با متد GET ارسال شده که نمونه Dio درخواست رو ارسال میکنه و منتظر میمونه تا جوابو دریافت کنه و بعد جواب رو تو کنسول چاپ میکنه. و همچنین سایت google در اولین پارمتر به عنوان url برای متد فرستاده میشه.متد POSTاز متد POST زمانی استفاده می‌کنیم که به عنوان مثال بخوایم چیزی رو برای سرور ارسال کنیم. import 'package:dio/dio.dart'; void postHttp() async { try { Dio dio= Dio(); Response response = dio.post(&quoturl.com&quot, data: {&quotid&quot: 12, &quotname&quot: &quotwendu&quot}); print(response); } catch (e) { print(e) } }تو این متد از روش پست استفاده کردیم و علاوه بر آدرس پارامتر data رو هم برای Dio ارسال کردیم. این پارامتر همون داده‌هایی هست که تو متدها POST و PUT برای API خودمون ارسال می‌کنیم. اگه از نرم‌افزار postman برای تست استفاده کرده باشین میتونین این پارامتر‌هارو تو تب body اضافه کنید.متد PUTمتد PUT معمولا زمانی استفاده میشه که می‌خواید مقادیری رو اپدیت کنید. import 'package:dio/dio.dart'; void putHttp() async { try { Dio dio= Dio(); Response response = dio.put(&quoturl.com&quot, data: {&quotid&quot: 12, &quotname&quot: &quotwendu&quot}); print(response); } catch (e) { print(e) } }این متد هم دقیقا مثل متد POST نوشته میشه.متد DELETEزمانی استفاده میشه که بخوایم یه مقدار رو حذف کنیم.import 'package:dio/dio.dart'; void deleteHttp() async { try { Dio dio= Dio(); Response response = dio.delete(&quoturl.com/2&quot); print(response); } catch (e) { print(e) } }تو این مثال درواقع داریم آیتمی با id دو رو حذف می‌کنیم. خوب تا اینجا که به نظرم کار خیلی ساده بود.رسیدگی به Error هاارور ها و اکسپشن ها مربوط به Dio با استفاده از کلاس DioError مورد بررسی قرار میگره. این به این معنیه که وقتی اررور یا اکسپشنی اتفاق میوفته در عبارت try-catch، یه ابجکت DioError پرتاپ میشه و ما با استفاده از catch اون رو مورد بررسی قرار میدیم. به تیکه کد زیر توجه کنید.try { //404 await dio.get(&quothttps://wendux.github.io/xsddddd&quot); } on DioError catch(e) { if(e.response) { print(e.response.data) print(e.response.headers) print(e.response.request) } else{ print(e.request) print(e.message) } }در کد بالا ما ابجک DioError رو گرفتیم و داده ها داخلش رو پرینت کردیم شما هم میتونید این کار رو انجام بدید. اما یه نکته مهم درمورد اررور ها وجود داره. اررور ها به دو دسته تقسیم میشن:ارور های سیستمیارور های response(پاسخ)از ارورای سیستمی میشه به خاموش بود کانکشن های اینترنت (مثل WiFi و دیتا) یا قطع بودن اینترنت اشاره کرد و ....و از اررور های پاسخ میشه به اررور 404 اشارده کرد( در واقع Dio هر ریسپانسی که status کدش بین 200 تا 300 نباشه رو به صورت یک اررور برمیگردونه- البته این اپشین قابل تنظیمه).کلاس Request Optionاین کلاس زمانی استفاده میشه که میخواید با استفاده از Dio یه درخواستی رو ارسال کنید. کار با این کلاس خیلی مهمه و با استفاده ازش میتونید درخواست هاتون رو شخصی سازی کنید. این کلاس از متغیر هایی زیر تشکیل شدهRequest Option { /// Http method. String method; /// Request base url, it can contain sub path, like: &quothttps://www.google.com/api/&quot. String baseUrl; /// Http request headers. Map<String, dynamic> headers; /// Timeout in milliseconds for opening url. int connectTimeout; /// Whenever more than [receiveTimeout] (in milliseconds) passes between two events from response stream, [Dio] will throw the [DioError] with [DioErrorType.RECEIVE_TIMEOUT]. int receiveTimeout; /// Request data, can be any type. T data; /// path will be added to base url String path=&quot&quot /// request content type String contentType; /// request Response type ResponseType responseType; /// `validateStatus` defines whether the request is successful ValidateStatus validateStatus; Map<String, dynamic> extra; /// Common query parameters Map<String, dynamic /*String|Iterable<String>*/ > queryParameters; }توضیحات مختصری درمورد هرکدوم از مقادیر بالا:متغیر Method: به عنوان نوع نوع درخواست http میشه ازش استفاده کرد. (Post, Put, Delete,Get)متغیر BaseUrl: به عنوان آدرس اصلی استفاده میشه. مثلا اگه دامنه Api هاتون مشخصه میشه این متغیر رو ثابت تعریف کنید.متغیر Headers: که با استفاده از یه Map میتونید هدر های درخواستتون رو مشخص کنید.متغیر connectTimeout و receiveTimeout: اولی برای تا زمان اتمام برقراری ارتباط و دومی برای زمان ارتباط دریافت جواب هستش.و مواردی که کاملا مشخص هستند و خودتون میتونید مطالعه کنید و از بحث این آموزش خارجه.با استفاده از این کلاس میتونید درخواست هاتون رو شخصی سازی کنید. همچنین میتونید یه ابجکت ثابت برای همه ی درخواست هاتون استفاده کنید. برای اینکار میتونید یه requestOption درست کنید و به وقتی دارین ابجکت Dio رو میسازید به این ابجکت پاسش کنید. به کد زیر نگاه کنید.استفاده از Dio در این پروژهما در این پروژه از Dio استفاده کردیم، و یه کلاس به اسم سرویس درست کردیم تا کارهای مربوط به ارتباط با سرور مون رو اونجا پیاده سازی کنیم. میتونید به آدرس زیر برید و با توجه به چیز هایی که یاد گرفتید کد مربوط به پیاده سازی Api رو مطاله کنید. https://github.com/payam-zahedi/featured-food-sample/blob/master/lib/api/service.dart لینک کلاستو کلاس بالا مهم ترین بخش، متد دریافت اطلاعات مربوط به غذاهاست. اگر به کد زیر نگاه کنید متوجه میشید که با استفاده از متد GET، یه درخواست به فایل /db ارسال کردیم و بعد از پارس کردن json یه لیستی از غذا هارو برمیگردونیم.static Future<FoodList> fetchData() async { try { Response response = await getInstance().get(&quot/db&quot); if (response.statusCode == 200) { // If server returns an OK response, parse the JSON. var jsonString = json.encode(response.data); Map userMap = jsonDecode(jsonString); return FoodList.fromJson(userMap); } else { // If that response was not OK, throw an error. throw DioError(message :'exception throwed in Try'); } } on DioError catch(e) { throw Exception(&quotSomeThing is Wrong: \n ${_checkError(e)}&quot); } }اگر پیشهاد، انتقاد یا نظری دارید خوشحال میشم که با به اشتراک گزاشتنش باعث بحبود عملکردم بشید ممنون.منابعhttps://pub.dev/packages/diohttps://medium.com/flutter-community/dio-interceptors-in-flutter-17be4214f363https://blog.usejournal.com/flutter-http-requests-with-dio-rxdart-and-bloc-da325ca5fe33