ایزی ریت
ورود / ثبت‌نامورود

اپ قیمت ارز با فلاتر (Flutter)؛ از JSON تا رابط کاربری راست‌چین

ساخت اپ قیمت ارز با فلاتر: مدل داده، دریافت JSON، سرور واسط برای حفظ کلید، RefreshIndicator، کش آفلاین، اعداد فارسی و رابط راست‌چین برای اندروید و iOS.

تینا نجفی
· نویسنده مالی و اقتصادی
انتشار ۱۷ آبان ۱۴۰۵، ۱۶:۰۰ · ۴ دقیقه مطالعه
اپ قیمت ارز با فلاتر (Flutter)؛ از JSON تا رابط کاربری راست‌چین
خلاصه در سه خط
  • اپ موبایل نباید کلید API را داخل خود داشته باشد؛ اپ از سرور شما بخواند و سرور از API.
  • با پکیج http و یک کلاس مدل، JSON نرخ‌ها را به لیست اشیای Dart تبدیل کنید و با FutureBuilder یا Riverpod نمایش دهید.
  • آخرین پاسخ را در shared_preferences ذخیره کنید تا اپ بدون اینترنت هم آخرین نرخ را با زمانش نشان دهد.

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

i
API ایزی‌ریت
این راهنما با API قیمت ارز و طلای ایزی‌ریت کار می‌کند؛ مستندات کامل، نمونه‌کد و کلید رایگان در صفحهٔ API است.
★
پاسخ کوتاه
یک مسیر روی سرور خودتان بسازید (مثلاً https://yourapp.com/rates) که با کلید از api.ezrate.me/v1/rates بخواند و کش کند. اپ فلاتر با پکیج http همان مسیر را می‌خواند، JSON را به List<Rate> تبدیل می‌کند و در ListView نمایش می‌دهد. آخرین پاسخ در shared_preferences ذخیره می‌شود.

این آموزش بخشی از راهنمای API قیمت است.

معماری: کلید هرگز داخل اپ نمی‌رود

هر فایل APK یا IPA را می‌توان باز کرد و رشته‌های داخل آن را خواند. اگر کلید API را در کد Dart بگذارید، دیر یا زود استخراج و سوءاستفاده می‌شود. راه درست یک لایه سرور کوچک است که هم کلید را نگه می‌دارد و هم پاسخ را برای همه کاربران کش می‌کند. این سرور می‌تواند همان بک‌اند اپ شما باشد یا یک تابع سرورلس ساده. جزئیات و نمونهٔ پروکسی در امنیت API Key در فرانت‌اند آمده است.

گام ۱: وابستگی‌ها

yaml
# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  http: ^1.2.0
  intl: ^0.19.0
  shared_preferences: ^2.2.0

گام ۲: مدل داده

dart
class Rate {
  final String symbol, name;
  final num buy, sell, changePct;
  final int sources;
  final DateTime updatedAt;

  Rate.fromJson(Map<String, dynamic> j)
      : symbol = j['symbol'],
        name = j['name'],
        buy = j['buy'],
        sell = j['sell'],
        changePct = j['change_pct'] ?? 0,
        sources = j['sources'] ?? 0,
        updatedAt = DateTime.parse(j['updated_at']);
}

گام ۳: سرویس دریافت نرخ با کش آفلاین

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

class RatesService {
  static const _url = 'https://yourapp.com/rates';   // سرور خودتان، نه api.ezrate.me
  static const _cacheKey = 'last_rates';

  Future<List<Rate>> load() async {
    final prefs = await SharedPreferences.getInstance();
    try {
      final res = await http.get(Uri.parse(_url)).timeout(const Duration(seconds: 8));
      if (res.statusCode == 200) {
        await prefs.setString(_cacheKey, res.body);       // آخرین پاسخ معتبر
        return _parse(res.body);
      }
    } catch (_) {/* بدون اینترنت یا خطای سرور */}
    final cached = prefs.getString(_cacheKey);
    return cached == null ? [] : _parse(cached);
  }

  List<Rate> _parse(String body) =>
      (jsonDecode(body)['data'] as List).map((e) => Rate.fromJson(e)).toList();
}

گام ۴: صفحه نرخ‌ها با رابط راست‌چین

dart
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

final _fa = NumberFormat.decimalPattern('fa');

class RatesPage extends StatefulWidget {
  const RatesPage({super.key});
  @override
  State<RatesPage> createState() => _RatesPageState();
}

class _RatesPageState extends State<RatesPage> {
  final _service = RatesService();
  List<Rate> _rates = [];

  Future<void> _refresh() async {
    final r = await _service.load();
    if (mounted) setState(() => _rates = r);
  }

  @override
  void initState() { super.initState(); _refresh(); }

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(title: const Text('قیمت لحظه‌ای بازار')),
        body: RefreshIndicator(
          onRefresh: _refresh,
          child: ListView.separated(
            itemCount: _rates.length,
            separatorBuilder: (_, __) => const Divider(height: 1),
            itemBuilder: (_, i) {
              final r = _rates[i];
              final up = r.changePct >= 0;
              return ListTile(
                title: Text(r.name),
                subtitle: Text('${r.sources} منبع'),
                trailing: Column(crossAxisAlignment: CrossAxisAlignment.end, children: [
                  Text('${_fa.format(r.sell)} تومان', style: const TextStyle(fontWeight: FontWeight.bold)),
                  Text('${up ? '▲' : '▼'} ${_fa.format(r.changePct.abs())}٪',
                      style: TextStyle(color: up ? Colors.green : Colors.red)),
                ]),
              );
            },
          ),
        ),
      );
}

برای راست‌چین شدن کامل، در MaterialApp مقدار locale: const Locale('fa') و supportedLocales و localizationsDelegates را تنظیم کنید. فلاتر جهت متن و چیدمان را خودش برعکس می‌کند. فونت فارسی مناسب (مثل وزیرمتن) را هم در pubspec.yaml اضافه کنید.

به‌روزرسانی دوره‌ای و مصرف باتری

وقتی صفحه باز است، می‌توانید با یک Timer.periodic هر ۶۰ ثانیه _refresh را صدا بزنید و در dispose آن را لغو کنید. وقتی اپ در پس‌زمینه است، تازه کردن مداوم فقط باتری مصرف می‌کند؛ برای خبر کردن کاربر از تغییرات مهم، سرور شما باید شرط را بررسی و نوتیفیکیشن (FCM) بفرستد. دلیل این تصمیم در WebSocket یا REST برای قیمت لحظه‌ای آمده است.

ویجت صفحه اصلی گوشی

کاربران اپ‌های قیمت، ویجت صفحهٔ اصلی (Home Screen Widget) را خیلی دوست دارند. فلاتر برای این کار پکیج home_widget دارد، اما بخش نمایش ویجت باید با کد بومی (Kotlin برای اندروید و SwiftUI برای iOS) نوشته شود. ساده‌ترین الگو: اپ در هر تازه‌سازی نرخ‌ها را در حافظهٔ مشترک بنویسد و ویجت فقط از آن بخواند.

قبل از انتشار در فروشگاه

  • در توضیحات اپ منبع نرخ‌ها را ذکر کنید و روشن بگویید نرخ‌ها جهت اطلاع است.
  • اگر اپ پرداخت درون‌برنامه‌ای دارد، قوانین Google Play و App Store دربارهٔ خرید محتوای دیجیتال را بررسی کنید.
  • اپ را با اینترنت قطع باز کنید: باید آخرین نرخ را با زمانش نشان دهد، نه صفحهٔ خالی.
  • نسخه انگلیسی این آموزش، همراه با React Native، در Flutter & React Native FX Tracker آمده است.
✓
پیشنهاد
اگر هدف شما فقط داشتن یک اپ قیمت برای خودتان یا مشتریانتان است، اپ EZRate برای اندروید و آیفون با ویجت صفحهٔ اصلی و هشدار قیمت آماده است.

انتشار اپ در فروشگاه‌ها

قبل از انتشار در گوگل‌پلی، بازار یا مایکت چند نکته را بررسی کنید: نام و توضیح اپ نباید ادعای «نرخ رسمی» داشته باشد، منبع داده و زمان به‌روزرسانی در اپ نمایش داده شود، و صفحهٔ حریم خصوصی داشته باشید. اگر اپ اعلان قیمت دارد، اجازهٔ اعلان را فقط وقتی کاربر هشدار می‌سازد درخواست کنید. برای اندروید، نسخهٔ APK آزمایشی را روی چند گوشی با اندازه‌های مختلف تست کنید تا جدول‌ها در صفحه‌های کوچک به‌هم نریزند.

برای ساخت اپ قیمت ارز با فلاتر حتماً سرور لازم است؟
برای حفظ امنیت کلید، بله. یک تابع سرورلس ساده هم کافی است. اپ نباید مستقیم با کلید به API درخواست بدهد.
چطور اعداد را فارسی نشان دهم؟
با NumberFormat.decimalPattern(&amp;#039;fa&amp;#039;) از پکیج intl. این فرمت ارقام و جداکنندهٔ هزارگان فارسی را می‌دهد.
اپ بدون اینترنت چه نشان دهد؟
آخرین نرخ ذخیره‌شده همراه زمان آن. صفحهٔ خالی یا خطای کلی تجربهٔ بدی است.
هر چند ثانیه نرخ را در اپ تازه کنم؟
هر ۶۰ ثانیه وقتی صفحه باز است. نرخ‌ها هر دقیقه محاسبه می‌شوند.
تینا نجفی
من در رشته مدیریت مالی تحصیل کرده‌ام و علاقه اصلی من به موضوعات مرتبط با بازار ارز، طلا، بانکداری و تجارت بین‌المللی است. در طول فعالیت حرفه‌ای خود، درباره موضوعات مالی و خدمات ارزی مطالعه و تحقیق کرده‌ام و تلاش می‌کنم مفاهیم پیچیده مالی را به شکل ساده و کاربردی توضیح دهم. در تهیه مطالب، سعی می‌کنم اطلاعات را از منابع معتبر بررسی کرده و محتوایی ارائه دهم که برای کاربران قابل فهم و قابل استفاده باشد.
همهٔ مطالب نویسنده ←

نظرات (۰)

نظرها پس از تأیید نمایش داده می‌شوند؛ برای ارسال، ورود به حساب لازم است.

مطالب مرتبط

API و برنامه‌نویسی
قیمت لحظه ای طلا در اکسل و گوگل شیت؛ اتصال به API بدون برنامه‌نویسی پیچیده
API و برنامه‌نویسی
مدیریت خطا در API مالی و Rate Limit: الگوهایی که سیستم را سرپا نگه می‌دارد
API و برنامه‌نویسی
وب سرویس نرخ درهم و لیر و یورو: راهنمای بازرگانی، گردشگری و دانشجویی