0

کار با api در فلاتر

بیایید با یک API ساده کار کنیم که بدون نیاز به احراز هویت به راحتی در دسترس است.

 

GET : /POSTS/1

بیایید بررسی کنیم که هنگام برخورد با این   API ، پاسخ ما چگونه خواهد بود. می توانید از postman استفاده کنید یا فقط این پیوند را در مرورگر خود paste کنید. به یاد داشته باشید ، اگر با API هایی که احتیاج به احراز هویت و سایر عناوین HTTP نیاز دارند کار می کنید ، توصیه می شود از Postman استفاده کنید.

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

این ابزار کلاس‌های مدل شما، روش‌های factory و روش‌های تبدیل را ایجاد خواهد کرد. برای نمونه اینجا را نگاه کنید.

بیایید فقط روی روش postFromJson  شما تمرکز کنیم.

Post postFromJson(String str) { 
 final jsonData = json.decode(str); 
 return Post.fromJson(jsonData);
}

str فقط رشته JSON ماست. پس از رمزگشایی str ، jsonData به این شکل است

این رشته  از طریق Post.fromJson تغذیه می شود تا factory بتواند یک شی Post جدید برای شما ایجاد کند که می توانید در برنامه خود استفاده کنید.

 

حالا باید API را صدا بزنیم

من بیشتر روشهای فراخوانی API را در فایل دیگری نگه میدارم ، فرض کنید نام آن services.dart باشد

String url = 'https://jsonplaceholder.typicode.com/posts';

Future<Post> getPost() async{
  final response = await http.get('$url/1');
  return postFromJson(response.body);
}

توجه: import پکیج های مورد نیاز را فراموش نکنید.

 

بنابراین تاکنون ، ما در مورد یک رشته JSON صحبت می کردیم ، اما هنوز حتی آن را نداریم. زیرا ما هرگز  API را فراخوانی نکردیم. بیایید ابتدا این کار را انجام دهیم.

متد api, getPost را که در url تعریف شده است فراخوانی می کند. و  به ما یک رشته JSON در پاسخ میدهد. body دریافت خواهیم کرد ، که باید آن را برای postFromJson ارسال کنیم تا بتواند جادوی تبدیل خود را انجام دهد.

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

پاسخ ما نیز در آینده در دسترس خواهد بود ، ما از Future استفاده می کنیم.

بدیهی است که می خواهیم روشی ناهمزمان برای فراخوانی API داشته باشیم. این همان جایی است که ما به همگام سازی و انتظار(async and await) نیاز داریم.async یک کلمه کلیدی است که متد شما را ناهمزمان می کند. در یک تابع async ، هنگامی که به

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

 

در مورد ساختن رابط کاربری برای پاسخی که دریافت کردم چطور؟

بله ، داشتیم به آنجا می رسیدم. بدیهی است ، اگر پاسخ خود را در future داشته باشیم ، رابط کاربری نیز باید بسته به پاسخ future  باشد.

چرا؟

زیرا ، رابط کاربری شما به محض اجرای برنامه ساخته می شود ، اما به محض اجرای برنامه پاسخ API خود را دریافت نمی کنید. بنابراین اگر رابط کاربری شما به مقادیر پاسخ API وابسته باشد ، خطاهای null زیادی برای شما ایجاد می کند.

.و برای حل این مشکل ، ما باید …

 

FutureBuilder

به زبان ساده ، در صورت وجود Futures ، از FutureBuilder برای ساخت ویجت استفاده کنید. بیایید خطوط کد زیر را در عملکرد ساخت UI خود اضافه کنیم.

FutureBuilder<Post>(
 future: getPost(),
 builder: (context, snapshot) {
 return Text('${snapshot.data.title}');
 }
)

FutureBuilder همچنین یک ویدجت است ، بنابراین می توانید آن را مستقیماً به Scaffold خود متصل کنید ، یا اینکه آن را عنوان child به هر ویدجت دیگری که دوست دارید وصل کنید.

FutureBuilder دو ویژگی اصلی دارد – future و builder.

بنابراین future متد () getPost را فراخوانی می کند ، این کار جادوی اتصال به  شبکه خود را انجام می دهد و نتیجه را به صورت snapshot از builder برمی گرداند. اکنون به سادگی ویدجت مورد نظر خود را با نتیجه داده شده ایجاد کنید.

if(snapshot.connectionState == ConnectionState.done)
 return Text('Title from Post JSON : ${snapshot.data.title}');POST /posts
else
return CircularProgressIndicator();

و فرض کنید می خواهم یک UI خاص را برای موقعیت های خطایی مانند No Internet Connection نشان دهم؟

if(snapshot.connectionState == ConnectionState.done) {
 if(snapshot.hasError){
 return ErrorWidget();
 }
 return Text('Title from Post JSON : ${snapshot.data.title}');
}

روشهای دیگری مانند snapshot.hasData و سایر ConnectionStates مانند ConnectionState.waiting ، ConnectionState.active وجود دارد. من به شما پیشنهاد می کنم برای ساخت برنامه های بهتر  همه آنها را آزمایش کنید.

 

POST /posts

سلام ، مطالب بالا اطلاعات زیادی در مورد درخواست GET بود. آیا می توانید به سرعت به من بگویید که چگونه درخواست POST را انجام دهم؟

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

Future<Post> createPost(Post post) async{
 final response = await http.post('$url',
 headers: {
 HttpHeaders.contentTypeHeader: 'application/json'
 },
 body: postToJson(post)
 );
 return postFromJson(response.body);
}

http.post شما اکنون از 3 پارامتر برخوردار است: url  ، هدرها (HTTP Headers ؛ در صورت لزوم) و body (اجباری)

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

PostToJson (post) شی پست شما را به یک رشته JSON آماده برای ارسال به سرور تبدیل می کند.

اکنون  روش createPost در FutureBuilder خود فراخوانی کنید و ویدجت خود را بسازید!

 

 

اما نمی خواهم برای این فراخونی شبکه UI ایجاد کنم

این یک سناریو ممکن است. مانند یک مورد استفاده از ورود به سیستم ، یا فقط یک تماس شبکه ای ساده که مقادیری را به سرور ارسال می کند ، و یک statusCode 200 یا 400 را برمی گرداند.

بنابراین FutureBuilder نمی خواهید؟

به سادگی از ()then استفاده کنید.

createPost(post).then(
(response){
 
}
)

در اینجا ،  response نتیجه نهایی است که ما با ایجاد  createPost بدست می آوریم. اکنون می توانیم از این پاسخ برای انجام هر کاری که می خواهیم استفاده کنیم. شاید به صفحه دیگری بروید.

createPost(post).then((response){
 Navigate.of(context).pushNamed('dashboard');
}

فرض کنید ما می خواهیم منطق خود را بر اساس کد موفقیت یا کد خطا کنترل کنیم ، باید روش createPost را اصلاح کنیم.

Future<http.Response> createPost(Post post) async{  //same as previous body  return response;
}

حال createPost یک Future از نوع http.Response را برمی گرداند. به این ترتیب می توانیم بسیاری از موارد را از طریق رابط کاربری خود کنترل کنیم.

createPost(post).then((response){
 if(response.statusCode == 200)
 Navigate.of(context).pushNamed('dashboard');
 else
print(response.statusCode);
})
ارسال دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *