0%
[ MERHABA ]
Ana içeriğe atla
TÜM MAKALELERE DÖN
•8 dk okuma

Flutter'da Canlı Harita ve Konum Tabanlı Servis Mimarisi Rehberi

Flutter mobil projelerinde Google Maps entegrasyonu, BLoC tabanlı konum dinleme, batarya optimizasyonu ve Clean Architecture rehberi.

NM
Nuh Mehmet Demirkol
Bilgisayar Mühendisi & Full Stack Developer
#Flutter#Konum Servisleri#Canlı Harita#BLoC#Mobil Geliştirme#Clean Architecture#Google Maps
Paylaş:

Giriş: Konum Tabanlı Uygulamaların Yükselişi ve Flutter'ın Gücü#

Kurye takip, mikromobilite (scooter/bisiklet kiralama), araç çağırma ve saha yönetim uygulamalarında kullanıcı deneyiminin kalbi gerçek zamanlı konum doğruluğu ve akıcı harita render performansından geçer.

Flutter, tek bir Dart kod tabanıyla hem iOS hem de Android platformlarında 60/120 FPS akıcı harita çizimleri yapabilmesi, gelişmiş platform kanalları (Platform Channels) ve zengin ekosistemi sayesinde konum tabanlı projeler için endüstri standardı haline gelmiştir.

Bu rehberde; harita kütüphanelerinin entegrasyonu, BLoC tabanlı durum yönetimi, batarya tasarrufu sağlayan konum dinleme filtreleri ve Clean Architecture mimari katmanlarını ele alıyoruz.


1. Mimari Tasarım: Clean Architecture Katmanları#

Canlı konum verisini UI bileşenleri içinde doğrudan dinlemek (spaghetti kod), bellek sızıntılarına (memory leak) ve kontrolsüz batarya tüketimine yol açar. Bu yüzden sorumlulukları net olarak ayırıyoruz:

  • Domain Katmanı: LocationEntity, GetLiveLocationStreamUseCase, CalculateDistanceUseCase. Platformdan bağımsız saf iş mantığı.
  • Data Katmanı: LocationRemoteDataSource (WebSocket/MQTT) ve LocationLocalDataSource (Geolocator GPS servisi).
  • Presentation Katmanı: BLoC / Cubit ile gelen konum akışını harita üzerindeki marker ve polyline objelerine dönüştüren reaktif katman.
dart
1// Domain: Saf Konum Modeli
2class UserLocation {
3 final double latitude;
4 final double longitude;
5 final double heading;
6 final double speed;
7 final DateTime timestamp;
8
9 const UserLocation({
10 required this.latitude,
11 required this.longitude,
12 required this.heading,
13 required this.speed,
14 required this.timestamp,
15 });
16}

2. Geolocator ile Optimize Edilmiş Konum Dinleme#

GPS modülü mobil cihazların en çok enerji harcayan donanımlarından biridir. Sürekli en yüksek hassasiyette (High Accuracy) konum istemek kullanıcının şarjını dakikalar içinde tüketebilir.

distanceFilter parametresi ile cihaz en az belirlenen metre kadar hareket etmedikçe yeni koordinat tetiklenmesini engelleyerek batarya kullanımını %40'a kadar optimize edebilirsiniz.
dart
1import 'dart:async';
2import 'package:geolocator/geolocator.dart';
3
4class LocationService {
5 StreamSubscription<Position>? _positionStreamSubscription;
6
7 Stream<Position> getLiveLocationStream({int distanceFilterMeters = 10}) {
8 final LocationSettings locationSettings = LocationSettings(
9 accuracy: LocationAccuracy.high,
10 distanceFilter: distanceFilterMeters,
11 );
12
13 return Geolocator.getPositionStream(locationSettings: locationSettings);
14 }
15
16 Future<bool> checkAndRequestPermission() async {
17 bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
18 if (!serviceEnabled) {
19 return false;
20 }
21
22 LocationPermission permission = await Geolocator.checkPermission();
23 if (permission == LocationPermission.denied) {
24 permission = await Geolocator.requestPermission();
25 if (permission == LocationPermission.denied) {
26 return false;
27 }
28 }
29
30 if (permission == LocationPermission.deniedForever) {
31 return false;
32 }
33
34 return true;
35 }
36
37 void dispose() {
38 _positionStreamSubscription?.cancel();
39 }
40}

3. BLoC ile Harita Durum Yönetimi#

Haritadaki kamera hareketi (CameraUpdate) ve marker rotasyonu, gelen konum akışına göre asenkron olarak güncellenmelidir.

dart
1// map_bloc.dart
2import 'package:flutter_bloc/flutter_bloc.dart';
3import 'package:google_maps_flutter/google_maps_flutter.dart';
4
5abstract class MapEvent {}
6class StartLiveTracking extends MapEvent {}
7class LocationUpdated extends MapEvent {
8 final LatLng position;
9 final double heading;
10 LocationUpdated(this.position, this.heading);
11}
12
13class MapState {
14 final LatLng? currentPosition;
15 final Set<Marker> markers;
16 final bool isTracking;
17
18 const MapState({
19 this.currentPosition,
20 this.markers = const {},
21 this.isTracking = false,
22 });
23
24 MapState copyWith({
25 LatLng? currentPosition,
26 Set<Marker>? markers,
27 bool? isTracking,
28 }) {
29 return MapState(
30 currentPosition: currentPosition ?? this.currentPosition,
31 markers: markers ?? this.markers,
32 isTracking: isTracking ?? this.isTracking,
33 );
34 }
35}

4. Google Maps UI Entegrasyonu & Akıcı Kamera Hareketi#

Flutter widget ağacında haritayı render ederken GoogleMap denetleyicisini (controller) hafızada doğru yönetmek gerekir.

dart
1class LiveMapScreen extends StatefulWidget {
2 const LiveMapScreen({super.key});
3
4 @override
5 State<LiveMapScreen> createState() => _LiveMapScreenState();
6}
7
8class _LiveMapScreenState extends State<LiveMapScreen> {
9 GoogleMapController? _mapController;
10
11 void _onMapCreated(GoogleMapController controller) {
12 _mapController = controller;
13 }
14
15 void _animateToPosition(LatLng position) {
16 _mapController?.animateCamera(
17 CameraUpdate.newCameraPosition(
18 CameraPosition(target: position, zoom: 16.5, tilt: 45.0),
19 ),
20 );
21 }
22
23 @override
24 Widget build(BuildContext context) {
25 return BlocConsumer<MapBloc, MapState>(
26 listener: (context, state) {
27 if (state.currentPosition != null) {
28 _animateToPosition(state.currentPosition!);
29 }
30 },
31 builder: (context, state) {
32 return Scaffold(
33 body: GoogleMap(
34 initialCameraPosition: const CameraPosition(
35 target: LatLng(39.9334, 32.8597), // Ankara
36 zoom: 14.0,
37 ),
38 onMapCreated: _onMapCreated,
39 markers: state.markers,
40 myLocationEnabled: true,
41 myLocationButtonEnabled: false,
42 zoomControlsEnabled: false,
43 ),
44 );
45 },
46 );
47 }
48}

5. Güvenlik ve Canlıya Alma Kontrol Listesi#

  • API Kısıtlamaları: Google Cloud Console üzerinden harita API anahtarınızı hem Android (SHA-1 fingerprint & package name) hem de iOS (Bundle Identifier) ile sınırlandırın.
  • İzin Açıklamaları: iOS için Info.plist dosyasında NSLocationWhenInUseUsageDescription ve NSLocationAlwaysAndWhenInUseUsageDescription metinlerini kullanıcıya şeffaf şekilde açıklayın.
  • Marker Kümeleme (Clustering): Haritada yüzlerce nokta gösterilecekse fluster veya google_maps_cluster_manager kütüphaneleriyle kümeleme yaparak UI donmalarını engelleyin.

Canlı harita ve konum mimarileri hakkında kurumsal veya özel projeniz için danışmanlık almak isterseniz iletişime geçebilirsiniz.

Pillar: Mobil MimariTopic Cluster / Konu Kümesi
Ana Çözüm Sayfasına Git (Pillar)

Flutter & Cross-Platform Mobil Uygulama Mühendisliği

iOS ve Android için Flutter ve Clean Architecture mimarisiyle sıfırdan anahtar teslim, yüksek performanslı ve mağaza garantili mobil uygulama geliştirme.

Temel Hizmet Mimarisi: Flutter Mobil Uygulama Geliştirme Firması | Nuh Mehmet Demirkol
Çözümü İncele

Bu rehberi faydalı buldunuz mu?

Geliştirici veya iş ortaklarınızla paylaşabilirsiniz.

Paylaş:

Bu Konuda Projeniz mi Var?

Makalede bahsedilen mimari çözümleri, mobil veya modern web projenizde sıfır hata ve maksimum performansla hayata geçirmek için doğrudan iletişime geçebilirsiniz.