دسترسی به REST API در برنامه نویسی فلاتر 

3 سال پیش

دسترسی به REST API در برنامه نویسی فلاتر 

در این درس از آموزش های برنامه نویسی سایت سورس باران، در مورد دسترسی به REST API در برنامه نویسی فلاتر صحبت می کنیم.

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

مفاهیم کلی 

پکیج http یک کلاس سطح بالا و http را برای انجام درخواست های وب فراهم می کند.

کلاس http قابلیت انجام انواع درخواست های HTTP را فراهم می کند.

متد های http یک آدرس اینترنتی و اطلاعات اضافی را از طریق نقشه دارت می پذیرند (داده های ارسال، عناوین اضافی و غیره.). از سرور درخواست می کند و پاسخ را با الگوی async/await جمع می کند. به عنوان مثال، کد زیر داده ها را از آدرس اینترنتی مشخص شده خوانده و آنها را در کنسول چاپ می کند.

print(await http.read('https://flutter.dev/'));

برخی از متد های اصلی به شرح زیر است –

  • url  -read مشخص شده را از طریق روش GET درخواست کنید و پاسخ را به عنوان <Future <String برگردانید
  • url  -get مشخص شده را از طریق روش GET درخواست کنید و پاسخ را به عنوان <Future <Response برگردانید. پاسخ کلاسی است که اطلاعات پاسخ را در خود نگه می دارد.
  • post – با ارسال داده های ارائه شده، آدرس url مشخص شده را از طریق POST درخواست کنید و پاسخ را به عنوان <Future <Response>برگردانید
  • put – آدرس url مشخص شده را از طریق روش PUT درخواست کنید و پاسخ را به عنوان Future <Response> برگردانید
  • head– آدرس url مشخص شده را از طریق روش HEAD درخواست کرده و پاسخ را به عنوان <Future <Response برگردانید
  • delete – آدرس url مشخص شده را از طریق روش DELETE درخواست کرده و پاسخ را به عنوان <Future <Response برگردانید

http همچنین یک کلاس استاندارد HTTP کلاینت ارائه می دهد. کلاینت از اتصال مداوم پشتیبانی می کند. هنگامی که درخواست زیادی از یک سرور خاص درخواست شود مفید خواهد بود. با استفاده از روش بستن باید به درستی بسته شود. در غیر این صورت، شبیه کلاس http است. کد نمونه به شرح زیر است –

var client = new http.Client(); 
try { 
   print(await client.get('https://flutter.dev/')); 
} 
finally { 
   client.close(); 
}

 

دسترسی به سرویس خدمات API

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

  • یک برنامه جدید Flutter در Android studio ، product_rest_app ایجاد کنید.
  • کد راه اندازی پیش فرض (main.dart) را با کد product_nav_app  جایگزین کنید.
  • پوشه assets را از Product_nav_app در Product_rest_app کپی کرده و assets را در داخل فایل pubspec.yaml اضافه کنید.
flutter: 
   assets: 
      - assets/appimages/floppy.png 
      - assets/appimages/iphone.png 
      - assets/appimages/laptop.png 
      - assets/appimages/pendrive.png 
      - assets/appimages/pixel.png 
      - assets/appimages/tablet.png

 

همانطور که در زیر نشان داده شده، پکیج http را در فایل pubspec.yaml پیکربندی کنید –

dependencies: 
   http: ^0.12.0+2

 

در اینجا، ما از آخرین نسخه پکیج http استفاده خواهیم کرد. Android studio هشدار پکیجی را ارسال می کند که pubspec.yaml به روز شده است.

Latest Version

گزینه دریافت وابستگی ها را کلیک کنید. Android studio پکیج را از اینترنت دریافت کرده و به درستی برای برنامه پیکربندی می کند.

پکیج http را در پرونده main.dart وارد کنید –

import 'dart:async'; 
import 'dart:convert'; 
import 'package:http/http.dart' as http;

 

همانطور که در زیر نشان داده شده است، یک فایل جدید JSON ، products.json با اطلاعات محصول ایجاد کنید

[ 
   { 
      "name": "iPhone", 
      "description": "iPhone is the stylist phone ever", 
      "price": 1000, 
      "image": "iphone.png" 
   }, 
   { 
      "name": "Pixel", 
      "description": "Pixel is the most feature phone ever", 
      "price": 800, 
      "image": "pixel.png"
   }, 
   { 
      "name": "Laptop", 
      "description": "Laptop is most productive development tool", 
      "price": 2000, 
      "image": "laptop.png" 
   }, 
   { 
      "name": "Tablet", 
      "description": "Tablet is the most useful device ever for meeting", 
      "price": 1500, 
      "image": "tablet.png" 
   }, 
   { 
      "name": "Pendrive", 
      "description": "Pendrive is useful storage medium", 
      "price": 100, 
      "image": "pendrive.png" 
   }, 
   { 
      "name": "Floppy Drive", 
      "description": "Floppy drive is useful rescue storage medium", 
      "price": 20, 
      "image": "floppy.png" 
   } 
]

 

یک فایل جدید ایجاد کنید، JSONWebServer و فایل JSON ، products.json را قرار دهید.

هر وب سروری را با JSONWebServer به عنوان دایرکتوری اصلی خود اجرا کنید و مسیر وب خود را دریافت کنید. به عنوان مثال:

  • http://192.168.184.1:8000/products.json. ما می توانیم از هر سرور وب مانند apache ، nginx و غیره استفاده کنیم ،
  • ساده ترین راه نصب برنامه مبتنی بر گره http-server است. برای نصب و اجرای برنامه سرور http مراحل زیر را دنبال کنید
  • برنامه Nodejs را نصب کنید (nodejs.org)
  • به پوشه JSONWebServer بروید.
cd /path/to/JSONWebServer
  • بسته سرور http را با استفاده از npm نصب کنید.
npm install -g http-server
  • اکنون، سرور را اجرا کنید.
http-server . -p 8000 

Starting up http-server, serving . 
Available on: 
   http://192.168.99.1:8000
   http://127.0.0.1:8000 
   Hit CTRL-C to stop the server

 

  • یک فایل جدید ، Product.dart در پوشه lib ایجاد کرده و کلاس Product را به داخل آن منتقل کنید.
  • یک سازنده کارخانه را در کلاس Product ، Product.fromMap بنویسید تا نقشه برداری داده را به شی Product تبدیل کند. به طور معمول، فایل JSON به شی دارت نقشه تبدیل شده و سپس به شی مربوطه تبدیل می شود (محصول).
factory Product.fromJson(Map<String, dynamic> data) {
   return Product(
      data['name'],
      data['description'], 
      data['price'],
      data['image'],
   );
}

 

کد کامل Product.dart به شرح زیر است –

class Product {
   final String name; 
   final String description;
   final int price;
   final String image; 
   
   Product(this.name, this.description, this.price, this.image); 
   factory Product.fromMap(Map<String, dynamic> json) { 
      return Product( 
         json['name'], 
         json['description'], 
         json['price'], 
         json['image'], 
      );
   }
}

 

برای واکشی و دانلود اطلاعات محصول از سرور وب در لیست List <Product> دو روش – تجزیه محصولات و واکشی محصولات – در کلاس اصلی بنویسید

List<Product> parseProducts(String responseBody) { 
   final parsed = json.decode(responseBody).cast<Map<String, dynamic>>(); 
   return parsed.map<Product>((json) =>Product.fromJson(json)).toList(); 
} 
Future<List<Product>> fetchProducts() async { 
   final response = await http.get('http://192.168.1.2:8000/products.json'); 
   if (response.statusCode == 200) { 
      return parseProducts(response.body); 
   } else { 
      throw Exception('Unable to fetch products from the REST API');
   } 
}

 

به نکات زیر در اینجا توجه کنید –

  • Future برای  lazy load اطلاعات محصول استفاده می شود. Lazy loading مفهومی برای به تعویق انداختن اجرای کد تا زمان ضرورت است.
  • http.get برای واکشی داده ها از اینترنت استفاده می شود.
  • json.decode برای رمزگشایی داده های JSON در شی دارت استفاده می شود. پس از رمزگشایی داده های JSON ، با استفاده از از نقشه کلاس Product به لیست <Product> تبدیل می شود.
  • در کلاس MyApp، متغیر عضو جدید محصولات از نوع <Future <Product اضافه کنید و آن را در سازنده قرار دهید.
class MyApp extends StatelessWidget { 
   final Future<List<Product>> products; 
   MyApp({Key key, this.products}) : super(key: key); 
   ...

 

  • در کلاس MyHomePage، محصولات متغیر عضو جدید را از نوع <Future <Product= اضافه کرده و در سازنده قرار دهید. همچنین، متغیر موارد و متد مربوط به آن را حذف کنید، فراخوانی متد getProducts. قرار دادن متغیر محصولات در سازنده این امکان را برای شما فراهم می کند تا هنگام شروع برنامه، محصولات را فقط یک بار از اینترنت واکشی کنید.
class MyHomePage extends StatelessWidget { 
   final String title; 
   final Future<ListList<Product>> products; 
   MyHomePage({Key key, this.title, this.products}) : super(key: key); 
   ...

 

  • گزینه (Home (MyHomePage را در روش ساخت ویجت MyApp تغییر دهید تا تغییرات بالا را در خود جای دهید –
home: MyHomePage(title: 'Product Navigation demo home page', products: products),

 

  • تابع اصلی را تغییر دهید تا شامل آرگومانهای <Future <Product شود –
void main() => runApp(MyApp(fetchProduct()));

 

برای ایجاد لیست محصولات در صفحه اصلی ، یک ویجت جدید ProductBoxList ایجاد کنید.

class ProductBoxList extends StatelessWidget { 
   final List<Product> items;
   ProductBoxList({Key key, this.items}); 
   
   @override 
   Widget build(BuildContext context) {
      return ListView.builder(
         itemCount: items.length,
         itemBuilder: (context, index) {
            return GestureDetector(
               child: ProductBox(item: items[index]), 
               onTap: () {
                  Navigator.push(
                     context, MaterialPageRoute(
                        builder: (context) =gt; ProductPage(item: items[index]), 
                     ), 
                  ); 
               }, 
            ); 
         }, 
      ); 
   } 
}

 

توجه داشته باشید که ما از همان مفهوم استفاده شده در برنامه پیمایش برای لیست محصولات استفاده کردیم، به جز اینکه با عبور محصولات (شی) از نوع <List <Product به عنوان یک ویجت جداگانه طراحی شده است.

  • در آخر، روش ساخت ویجت MyHomePage را تغییر دهید تا اطلاعات محصول را به جای فراخوانی با متد عادی با استفاده از گزینه Future بدست آورید.
Widget build(BuildContext context) { 
   return Scaffold(
      appBar: AppBar(title: Text("Product Navigation")),
      body: Center(
         child: FutureBuilder<List<Product>>(
            future: products, builder: (context, snapshot) {
               if (snapshot.hasError) print(snapshot.error); 
               return snapshot.hasData ? ProductBoxList(items: snapshot.data)
               
               // return the ListView widget : 
               Center(child: CircularProgressIndicator()); 
            }, 
         ), 
      )
   ); 
}

 

در اینجا توجه داشته باشید که ما از ویجت FutureBuilder برای ارائه ویجت استفاده کردیم. FutureBuilder سعی می کند داده ها را از ویژگی Future خود دریافت کند (از نوع <Future <List <Product>). اگر ویژگی Future داده ها را بازگرداند، ویجت را با استفاده از ProductBoxList ارائه می دهد، در غیر این صورت خطایی ایجاد می شود.

کد کامل main.dart به شرح زیر است:

import 'package:flutter/material.dart'; 
import 'dart:async'; 
import 'dart:convert'; 
import 'package:http/http.dart' as http; 
import 'Product.dart'; 

void main() => runApp(MyApp(products: fetchProducts())); 

List<Product> parseProducts(String responseBody) { 
   final parsed = json.decode(responseBody).cast<Map<String, dynamic>>(); 
   return parsed.map<Product>((json) => Product.fromMap(json)).toList(); 
} 
Future<List<Product>> fetchProducts() async { 
   final response = await http.get('http://192.168.1.2:8000/products.json'); 
   if (response.statusCode == 200) { 
      return parseProducts(response.body); 
   } else { 
      throw Exception('Unable to fetch products from the REST API'); 
   } 
}
class MyApp extends StatelessWidget {
   final Future<List<Product>> products; 
   MyApp({Key key, this.products}) : super(key: key); 
   
   // This widget is the root of your application. 
   @override 
   Widget build(BuildContext context) {
      return MaterialApp(
         title: 'Flutter Demo', 
         theme: ThemeData( 
            primarySwatch: Colors.blue, 
         ), 
         home: MyHomePage(title: 'Product Navigation demo home page', products: products), 
      ); 
   }
}
class MyHomePage extends StatelessWidget { 
   final String title; 
   final Future<List<Product>> products; 
   MyHomePage({Key key, this.title, this.products}) : super(key: key); 
   
   // final items = Product.getProducts();
   @override 
   Widget build(BuildContext context) { 
      return Scaffold(
         appBar: AppBar(title: Text("Product Navigation")), 
         body: Center(
            child: FutureBuilder<List<Product>>(
               future: products, builder: (context, snapshot) {
                  if (snapshot.hasError) print(snapshot.error); 
                  return snapshot.hasData ? ProductBoxList(items: snapshot.data) 
                  
                  // return the ListView widget : 
                  Center(child: CircularProgressIndicator()); 
               },
            ),
         )
      );
   }
}
class ProductBoxList extends StatelessWidget {
   final List<Product> items; 
   ProductBoxList({Key key, this.items}); 
   
   @override 
   Widget build(BuildContext context) {
      return ListView.builder(
         itemCount: items.length, 
         itemBuilder: (context, index) { 
            return GestureDetector( 
               child: ProductBox(item: items[index]), 
               onTap: () { 
                  Navigator.push(
                     context, MaterialPageRoute( 
                        builder: (context) => ProductPage(item: items[index]), 
                     ), 
                  ); 
               }, 
            ); 
         }, 
      ); 
   } 
} 
class ProductPage extends StatelessWidget { 
   ProductPage({Key key, this.item}) : super(key: key); 
   final Product item; 
   @override 
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(title: Text(this.item.name),), 
         body: Center( 
            child: Container(
               padding: EdgeInsets.all(0), 
               child: Column( 
                  mainAxisAlignment: MainAxisAlignment.start, 
                  crossAxisAlignment: CrossAxisAlignment.start, 
                  children: <Widget>[
                     Image.asset("assets/appimages/" + this.item.image), 
                     Expanded( 
                        child: Container( 
                           padding: EdgeInsets.all(5), 
                           child: Column( 
                              mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                              children: <Widget>[ 
                                 Text(this.item.name, style: 
                                    TextStyle(fontWeight: FontWeight.bold)), 
                                 Text(this.item.description), 
                                 Text("Price: " + this.item.price.toString()), 
                                 RatingBox(), 
                              ], 
                           )
                        )
                     ) 
                  ]
               ), 
            ), 
         ), 
      ); 
   } 
}
class RatingBox extends StatefulWidget { 
   @override 
   _RatingBoxState createState() =>_RatingBoxState(); 
} 
class _RatingBoxState extends State<RatingBox> { 
   int _rating = 0; 
   void _setRatingAsOne() {
      setState(() { 
         _rating = 1; 
      }); 
   }
   void _setRatingAsTwo() {
      setState(() {
         _rating = 2; 
      }); 
   }
   void _setRatingAsThree() { 
      setState(() {
         _rating = 3; 
      }); 
   }
   Widget build(BuildContext context) {
      double _size = 20; 
      print(_rating); 
      return Row(
         mainAxisAlignment: MainAxisAlignment.end, 
         crossAxisAlignment: CrossAxisAlignment.end, 
         mainAxisSize: MainAxisSize.max, 
         
         children: <Widget>[
            Container(
               padding: EdgeInsets.all(0), 
               child: IconButton( 
                  icon: (
                     _rating >= 1 
                     ? Icon(Icons.star, ize: _size,) 
                     : Icon(Icons.star_border, size: _size,)
                  ), 
                  color: Colors.red[500], onPressed: _setRatingAsOne, iconSize: _size, 
               ), 
            ), 
            Container(
               padding: EdgeInsets.all(0), 
               child: IconButton(
                  icon: (
                     _rating >= 2 
                     ? Icon(Icons.star, size: _size,) 
                     : Icon(Icons.star_border, size: _size, )
                  ), 
                  color: Colors.red[500], 
                  onPressed: _setRatingAsTwo, 
                  iconSize: _size, 
               ), 
            ), 
            Container(
               padding: EdgeInsets.all(0), 
               child: IconButton(
                  icon: (
                     _rating >= 3 ? 
                     Icon(Icons.star, size: _size,)
                     : Icon(Icons.star_border, size: _size,)
                  ), 
                  color: Colors.red[500], 
                  onPressed: _setRatingAsThree, 
                  iconSize: _size, 
               ), 
            ), 
         ], 
      ); 
   } 
}
class ProductBox extends StatelessWidget {
   ProductBox({Key key, this.item}) : super(key: key); 
   final Product item; 
   
   Widget build(BuildContext context) {
      return Container(
         padding: EdgeInsets.all(2), height: 140, 
         child: Card(
            child: Row( 
               mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
               children: <Widget>[
                  Image.asset("assets/appimages/" + this.item.image), 
                  Expanded( 
                     child: Container( 
                        padding: EdgeInsets.all(5), 
                        child: Column( 
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                           children: <Widget>[ 
                              Text(this.item.name, style:TextStyle(fontWeight: FontWeight.bold)), 
                              Text(this.item.description), 
                              Text("Price: " + this.item.price.toString()), 
                              RatingBox(), 
                           ], 
                        )
                     )
                  )
               ]
            ), 
         )
      ); 
   } 
}

 

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

منبع.

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

  1. معرفی برنامه نویسی فلاتر
  2. آموزش نصب فلاتر
  3. اصول ایجاد یک برنامه فلاتر در Android Studio
  4. معماری فریم ورک برنامه نویسی فلاتر
  5. مقدمه ای بر برنامه نویسی دارت
  6. مقدمه ای بر ویجت ها در برنامه نویسی فلاتر
  7. آموزش طرح بندی در برنامه نویسی فلاتر 
  8. ژست های حرکتی در برنامه نویسی فلاتر 
  9. مدیریت State در برنامه نویسی فلاتر
  10. آموزش انیمیشن در برنامه نویسی فلاتر
  11. آموزش نوشتن کد خاص اندروید در برنامه نویسی فلاتر
  12. آموزش نوشتن کد مخصوص IOS در برنامه نویسی فلاتر
  13. مقدمه ای بر پکیج ها در برنامه نویسی فلاتر 

 

0
برچسب ها :
نویسنده مطلب erfan molaei

دیدگاه شما

بدون دیدگاه