UAE Cities & Areas for Flutter

A Flutter plugin for UAE cities, areas, and locations. Fetch all emirates and their areas from the UAE API with built-in persistent caching—ideal for location pickers, address forms, and region selection in Flutter apps.

Features

  • 🏙️ Fetch UAE cities and emirates with English and Arabic names
  • 📍 Fetch areas and locations for any emirate or city
  • 💾 Persistent storage caching (survives app restarts)
  • 🔄 Force refresh option to bypass cache
  • ⚡ Fast offline support with cached data
  • 🎯 Simple and intuitive API for UAE locations in Flutter

Installation

Add the UAE cities and areas plugin to your Flutter app's pubspec.yaml:

dependencies:
  uae_city_areas:
    path: ../path/to/uae_city_areas  # or use git/pub.dev if published
  http: ^1.0.0  # Add version you want to use
  shared_preferences: ^2.2.0  # Add version you want to use

Note: The plugin doesn't specify dependency versions, so you must add http and shared_preferences with your preferred versions in your app's pubspec.yaml.

Usage

Basic Usage (no object creation)

Call the plugin directly via static methods:

import 'package:uae_city_areas/uae_city_areas.dart';

// Fetch cities (no need to create any object)
final cities = await UAECityAreasPlugin.getCities();

// Fetch areas for a city
final areas = await UAECityAreasPlugin.getAreasByCityId(cityId);

Force Refresh

final cities = await UAECityAreasPlugin.getCities(forceRefresh: true);
final areas = await UAECityAreasPlugin.getAreasByCityId(cityId, forceRefresh: true);

Cache Management

await UAECityAreasPlugin.clearCache();
await UAECityAreasPlugin.clearCitiesCache();
await UAECityAreasPlugin.clearAreasCache(cityId);   // or null to clear all

Error Handling

try {
  final cities = await UAECityAreasPlugin.getCities();
} on NetworkException catch (e) {
  // Handle network error
} on ApiException catch (e) {
  // Handle API error (e.statusCode, e.message)
} on ParseException catch (e) {
  // Handle parsing error
} on CitiesAreasException catch (e) {
  // Handle other plugin errors
}

Logging

Logging is off by default. Enable it to print plugin actions (API calls, cache hits/misses) to the console:

import 'package:uae_city_areas/uae_city_areas.dart';

void main() {
  UAECityAreasPlugin.loggingEnabled = true;  // Enable plugin logging
  runApp(MyApp());
}

API

UAECityAreasPlugin (static – use this, no object creation)

Call these directly:

  • UAECityAreasPlugin.getCities({bool forceRefresh = false}) - Fetch all cities/emirates
  • UAECityAreasPlugin.getAreasByCityId(int cityId, {bool forceRefresh = false}) - Fetch areas for a city
  • UAECityAreasPlugin.getAreasByCity(City city, {bool forceRefresh = false}) - Fetch areas by City object
  • UAECityAreasPlugin.clearCache() - Clear all cached data
  • UAECityAreasPlugin.clearCitiesCache() - Clear only cities cache
  • UAECityAreasPlugin.clearAreasCache(int? cityId) - Clear areas cache (specific city or all)
  • UAECityAreasPlugin.loggingEnabled - Get or set plugin logging (default: false)

Models

City

class City {
  final int id;           // City/emirate ID
  final String name;      // English name
  final String nameArabic; // Arabic name
}

Area

class Area {
  final int id;          // Area ID
  final String name;     // Area name
  final int emirateId;    // ID of the emirate/city
}

Exceptions

  • CitiesAreasException - Base exception
  • NetworkException - Network/connection errors
  • ApiException - API errors (includes statusCode)
  • ParseException - JSON parsing errors
  • CacheException - Cache operation errors

Caching

The plugin uses persistent storage caching with shared_preferences:

  • Default behavior: Returns cached data if available, otherwise fetches from API
  • Force refresh: Bypasses cache and fetches fresh data
  • TTL support: Optional time-to-live for cache expiration
  • Offline support: Works offline with cached data

Cache persists across app restarts, so subsequent launches are instant.

Example: Get cities and areas for a city

import 'package:uae_city_areas/uae_city_areas.dart';

Future<void> loadCitiesAndAreas() async {
  // 1. Get all cities (emirates)
  final cities = await UAECityAreasPlugin.getCities();
  if (cities.isEmpty) return;

  // 2. Pick a city (e.g. first one, or by user selection)
  final selectedCity = cities.first;

  // 3. Get areas for that city (by ID or by City object)
  final areas = await UAECityAreasPlugin.getAreasByCityId(selectedCity.id);
  // Or: final areas = await UAECityAreasPlugin.getAreasByCity(selectedCity);

  // Use the data
  for (final city in cities) {
    print('${city.name} (${city.nameArabic})');
  }
  for (final area in areas) {
    print('  - ${area.name}');
  }
}

With force refresh (bypass cache):

final cities = await UAECityAreasPlugin.getCities(forceRefresh: true);
final areas = await UAECityAreasPlugin.getAreasByCityId(cityId, forceRefresh: true);

Example app

See the example/ directory for a complete Flutter app with city and area dropdowns.

cd example
flutter pub get
flutter run

License

See LICENSE file for details.

Libraries

uae_city_areas
UAE Cities & Areas for Flutter - A plugin for fetching cities/emirates and areas