Skip to content

Mobil-Spesifik Ağ Hususları

Batarya Optimizasyonu

Ağ Verimliliği

Mobile cihazlarda battery life kritik bir faktördür ve network operations en büyük battery drain sebeplerinden biridir.

İstek Birleştirme

javascript
class RequestCoalescer {
  constructor(windowSize = 100) {
    this.windowSize = windowSize;
    this.pendingRequests = [];
    this.coalesceTimer = null;
  }

  addRequest(request) {
    this.pendingRequests.push(request);
    
    if (!this.coalesceTimer) {
      this.coalesceTimer = setTimeout(() => {
        this.processBatchedRequests();
      }, this.windowSize);
    }
  }

  processBatchedRequests() {
    if (this.pendingRequests.length === 0) return;
    
    // Similar requests'leri grupla
    const groupedRequests = this.groupSimilarRequests(this.pendingRequests);
    
    // Her grup için batch request gönder
    groupedRequests.forEach(group => {
      this.sendBatchRequest(group);
    });
    
    this.pendingRequests = [];
    this.coalesceTimer = null;
  }

  groupSimilarRequests(requests) {
    const groups = new Map();
    
    requests.forEach(request => {
      const key = `${request.method}-${request.baseUrl}`;
      if (!groups.has(key)) {
        groups.set(key, []);
      }
      groups.get(key).push(request);
    });
    
    return Array.from(groups.values());
  }

  async sendBatchRequest(requests) {
    if (requests.length === 1) {
      return this.sendSingleRequest(requests[0]);
    }

    // Multiple requests'i tek bir batch request'e dönüştür
    const batchPayload = {
      requests: requests.map(req => ({
        id: req.id,
        method: req.method,
        url: req.url,
        data: req.data
      }))
    };

    try {
      const response = await fetch('/api/batch', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(batchPayload)
      });

      const batchResult = await response.json();
      
      // Results'ları individual promises'a distribute et
      batchResult.responses.forEach(result => {
        const originalRequest = requests.find(req => req.id === result.id);
        if (originalRequest) {
          if (result.success) {
            originalRequest.resolve(result.data);
          } else {
            originalRequest.reject(new Error(result.error));
          }
        }
      });
    } catch (error) {
      requests.forEach(req => req.reject(error));
    }
  }
}

Background Sync Strategy

javascript
class BackgroundSyncManager {
  constructor() {
    this.syncQueue = [];
    this.isOnline = navigator.onLine;
    this.syncInProgress = false;
    
    // Network durumu değişikliklerini dinle
    window.addEventListener('online', () => {
      this.isOnline = true;
      this.processSyncQueue();
    });
    
    window.addEventListener('offline', () => {
      this.isOnline = false;
    });
  }

  queueForSync(operation) {
    this.syncQueue.push({
      ...operation,
      timestamp: Date.now(),
      retries: 0
    });
    
    if (this.isOnline && !this.syncInProgress) {
      this.processSyncQueue();
    }
  }

  async processSyncQueue() {
    if (this.syncInProgress || !this.isOnline) return;
    
    this.syncInProgress = true;
    
    while (this.syncQueue.length > 0 && this.isOnline) {
      const operation = this.syncQueue.shift();
      
      try {
        await this.executeOperation(operation);
      } catch (error) {
        console.error('Sync operation failed:', error);
        
        if (operation.retries < 3) {
          operation.retries++;
          this.syncQueue.unshift(operation); // Retry
        } else {
          console.error('Max retries reached for operation:', operation);
        }
      }
      
      // Battery'yi korumak için operations arasında delay
      await this.delay(100);
    }
    
    this.syncInProgress = false;
  }

  async executeOperation(operation) {
    switch (operation.type) {
      case 'create':
        return await this.createResource(operation.resource, operation.data);
      case 'update':
        return await this.updateResource(operation.resource, operation.id, operation.data);
      case 'delete':
        return await this.deleteResource(operation.resource, operation.id);
      default:
        throw new Error(`Unknown operation type: ${operation.type}`);
    }
  }

  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

Push Notifications vs Polling

javascript
class EfficientDataFetcher {
  constructor() {
    this.pollingIntervals = new Map();
    this.pushNotificationSupported = 'serviceWorker' in navigator && 'PushManager' in window;
  }

  // Push notifications kullanarak real-time updates
  async setupPushNotifications() {
    if (!this.pushNotificationSupported) {
      console.log('Push notifications desteklenmiyor, polling\'e geri dön');
      return this.fallbackToPolling();
    }

    try {
      const registration = await navigator.serviceWorker.ready;
      const subscription = await registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: this.urlBase64ToUint8Array(VAPID_PUBLIC_KEY)
      });

      // Subscription'ı server'a gönder
      await this.sendSubscriptionToServer(subscription);
      
      console.log('Push notifications kuruldu');
    } catch (error) {
      console.error('Push notification setup failed:', error);
      this.fallbackToPolling();
    }
  }

  // Fallback: Adaptive polling
  fallbackToPolling() {
    this.startAdaptivePolling();
  }

  startAdaptivePolling() {
    let pollInterval = 30000; // 30 saniye başla
    let consecutiveEmptyResponses = 0;
    
    const poll = async () => {
      try {
        const updates = await this.checkForUpdates();
        
        if (updates.length === 0) {
          consecutiveEmptyResponses++;
          // Boş response'larda interval'ı artır (max 5 dakika)
          pollInterval = Math.min(pollInterval * 1.2, 300000);
        } else {
          consecutiveEmptyResponses = 0;
          // Update varsa interval'ı azalt
          pollInterval = Math.max(pollInterval * 0.8, 10000);
          this.processUpdates(updates);
        }
        
        setTimeout(poll, pollInterval);
      } catch (error) {
        console.error('Polling failed:', error);
        setTimeout(poll, pollInterval * 2); // Error durumunda daha uzun bekle
      }
    };
    
    poll();
  }

  async checkForUpdates() {
    const response = await fetch('/api/updates', {
      headers: {
        'If-None-Match': this.lastETag || '',
        'If-Modified-Since': this.lastModified || ''
      }
    });
    
    if (response.status === 304) {
      return []; // No updates
    }
    
    this.lastETag = response.headers.get('ETag');
    this.lastModified = response.headers.get('Last-Modified');
    
    return await response.json();
  }
}

Resource Management

CPU Usage Optimization

javascript
class CPUOptimizedNetworking {
  constructor() {
    this.requestQueue = [];
    this.maxConcurrentRequests = this.detectOptimalConcurrency();
    this.activeRequests = 0;
  }

  detectOptimalConcurrency() {
    // Device capabilities'e göre optimal concurrency belirle
    const cores = navigator.hardwareConcurrency || 2;
    const memory = navigator.deviceMemory || 1; // GB
    
    // Low-end device detection
    if (memory <= 1 || cores <= 2) {
      return 2; // Conservative
    } else if (memory <= 4 || cores <= 4) {
      return 4; // Moderate
    } else {
      return 6; // Aggressive
    }
  }

  async makeRequest(url, options = {}) {
    return new Promise((resolve, reject) => {
      this.requestQueue.push({ url, options, resolve, reject });
      this.processQueue();
    });
  }

  async processQueue() {
    if (this.activeRequests >= this.maxConcurrentRequests || this.requestQueue.length === 0) {
      return;
    }

    const request = this.requestQueue.shift();
    this.activeRequests++;

    try {
      const response = await fetch(request.url, request.options);
      request.resolve(response);
    } catch (error) {
      request.reject(error);
    } finally {
      this.activeRequests--;
      // Process next request
      setTimeout(() => this.processQueue(), 0);
    }
  }

  // Request priority ile CPU usage'ı optimize et
  prioritizeRequest(url, options = {}, priority = 'normal') {
    const request = { url, options, priority, timestamp: Date.now() };
    
    if (priority === 'high') {
      this.requestQueue.unshift(request);
    } else {
      this.requestQueue.push(request);
    }
    
    this.processQueue();
  }
}

Memory Footprint Management

javascript
class MemoryEfficientCache {
  constructor(maxSize = 50 * 1024 * 1024) { // 50MB default
    this.maxSize = maxSize;
    this.currentSize = 0;
    this.cache = new Map();
    this.accessTimes = new Map();
  }

  set(key, data) {
    const size = this.calculateSize(data);
    
    // Memory pressure kontrolü
    if (this.currentSize + size > this.maxSize) {
      this.evictLRU(size);
    }
    
    this.cache.set(key, data);
    this.accessTimes.set(key, Date.now());
    this.currentSize += size;
  }

  get(key) {
    if (this.cache.has(key)) {
      this.accessTimes.set(key, Date.now());
      return this.cache.get(key);
    }
    return null;
  }

  evictLRU(requiredSize) {
    // LRU eviction ile memory'yi temizle
    const sortedByAccess = Array.from(this.accessTimes.entries())
      .sort((a, b) => a[1] - b[1]);
    
    let freedSize = 0;
    
    for (const [key, _] of sortedByAccess) {
      if (freedSize >= requiredSize) break;
      
      const data = this.cache.get(key);
      const size = this.calculateSize(data);
      
      this.cache.delete(key);
      this.accessTimes.delete(key);
      this.currentSize -= size;
      freedSize += size;
    }
  }

  calculateSize(data) {
    // Rough size calculation
    return JSON.stringify(data).length * 2; // UTF-16 characters
  }

  // Memory pressure detection
  onMemoryPressure() {
    // Aggressive cleanup on memory pressure
    const targetSize = this.maxSize * 0.5; // Reduce to 50%
    this.evictLRU(this.currentSize - targetSize);
  }
}

Platform-Specific Battery Optimization

Android Battery Optimization

kotlin
class AndroidBatteryOptimizer(private val context: Context) {
    private val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
    private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    
    fun isDeviceInPowerSaveMode(): Boolean {
        return powerManager.isPowerSaveMode
    }
    
    fun isOnMeteredConnection(): Boolean {
        val networkInfo = connectivityManager.activeNetworkInfo
        return connectivityManager.isActiveNetworkMetered
    }
    
    fun optimizeForBattery(): NetworkConfiguration {
        val config = NetworkConfiguration()
        
        when {
            isDeviceInPowerSaveMode() -> {
                config.requestTimeout = 60000 // Longer timeout
                config.maxConcurrentRequests = 1 // Single request
                config.retryPolicy = ConservativeRetryPolicy()
            }
            isOnMeteredConnection() -> {
                config.compressionEnabled = true
                config.imageCacheEnabled = true
                config.prefetchingEnabled = false
            }
            else -> {
                config.loadDefaultConfiguration()
            }
        }
        
        return config
    }
    
    fun scheduleBackgroundSync() {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .setRequiresBatteryNotLow(true)
            .build()
            
        val syncWork = OneTimeWorkRequestBuilder<BackgroundSyncWorker>()
            .setConstraints(constraints)
            .build()
            
        WorkManager.getInstance(context).enqueue(syncWork)
    }
}

iOS Battery Optimization

swift
class iOSBatteryOptimizer {
    private let processInfo = ProcessInfo.processInfo
    
    var isLowPowerModeEnabled: Bool {
        return processInfo.isLowPowerModeEnabled
    }
    
    var thermalState: ProcessInfo.ThermalState {
        return processInfo.thermalState
    }
    
    func optimizeForBattery() -> NetworkConfiguration {
        let config = NetworkConfiguration()
        
        switch (isLowPowerModeEnabled, thermalState) {
        case (true, _):
            config.requestTimeout = 60.0
            config.maxConcurrentRequests = 1
            config.backgroundTasksEnabled = false
            
        case (_, .critical), (_, .serious):
            config.requestTimeout = 30.0
            config.maxConcurrentRequests = 2
            config.throttleRequests = true
            
        default:
            config.loadDefaultConfiguration()
        }
        
        return config
    }
    
    func scheduleBackgroundRefresh() {
        let identifier = "com.app.backgroundrefresh"
        let request = BGAppRefreshTaskRequest(identifier: identifier)
        request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 minutes
        
        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Background refresh scheduling failed: \(error)")
        }
    }
}

Offline Support

Data Persistence

Local Storage Strategy

javascript
class OfflineStorageManager {
  constructor() {
    this.dbName = 'OfflineApp';
    this.dbVersion = 1;
    this.db = null;
    this.initDB();
  }

  async initDB() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.dbVersion);
      
      request.onerror = () => reject(request.error);
      request.onsuccess = () => {
        this.db = request.result;
        resolve(this.db);
      };
      
      request.onupgradeneeded = (event) => {
        const db = event.target.result;
        
        // Entities store
        if (!db.objectStoreNames.contains('entities')) {
          const entityStore = db.createObjectStore('entities', { keyPath: 'id' });
          entityStore.createIndex('type', 'type', { unique: false });
          entityStore.createIndex('lastModified', 'lastModified', { unique: false });
        }
        
        // Sync queue store
        if (!db.objectStoreNames.contains('syncQueue')) {
          const syncStore = db.createObjectStore('syncQueue', { keyPath: 'id', autoIncrement: true });
          syncStore.createIndex('priority', 'priority', { unique: false });
          syncStore.createIndex('timestamp', 'timestamp', { unique: false });
        }
        
        // Cache store
        if (!db.objectStoreNames.contains('cache')) {
          const cacheStore = db.createObjectStore('cache', { keyPath: 'key' });
          cacheStore.createIndex('expiry', 'expiry', { unique: false });
        }
      };
    });
  }

  async saveEntity(entity) {
    const transaction = this.db.transaction(['entities'], 'readwrite');
    const store = transaction.objectStore('entities');
    
    const entityWithTimestamp = {
      ...entity,
      lastModified: Date.now(),
      syncStatus: 'pending'
    };
    
    return new Promise((resolve, reject) => {
      const request = store.put(entityWithTimestamp);
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  async getEntity(id) {
    const transaction = this.db.transaction(['entities'], 'readonly');
    const store = transaction.objectStore('entities');
    
    return new Promise((resolve, reject) => {
      const request = store.get(id);
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  async getEntitiesByType(type) {
    const transaction = this.db.transaction(['entities'], 'readonly');
    const store = transaction.objectStore('entities');
    const index = store.index('type');
    
    return new Promise((resolve, reject) => {
      const request = index.getAll(type);
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  async getPendingSyncItems() {
    const transaction = this.db.transaction(['entities'], 'readonly');
    const store = transaction.objectStore('entities');
    
    return new Promise((resolve, reject) => {
      const request = store.getAll();
      request.onsuccess = () => {
        const pendingItems = request.result.filter(item => item.syncStatus === 'pending');
        resolve(pendingItems);
      };
      request.onerror = () => reject(request.error);
    });
  }
}

Sync Queue Management

javascript
class SyncQueueManager {
  constructor(storageManager) {
    this.storage = storageManager;
    this.syncInProgress = false;
    this.retryDelays = [1000, 2000, 5000, 10000, 30000]; // Progressive delays
  }

  async queueOperation(operation) {
    const queueItem = {
      ...operation,
      timestamp: Date.now(),
      retries: 0,
      priority: operation.priority || 'normal'
    };

    const transaction = this.storage.db.transaction(['syncQueue'], 'readwrite');
    const store = transaction.objectStore('syncQueue');
    
    return new Promise((resolve, reject) => {
      const request = store.add(queueItem);
      request.onsuccess = () => {
        resolve(request.result);
        this.processQueue(); // Start processing
      };
      request.onerror = () => reject(request.error);
    });
  }

  async processQueue() {
    if (this.syncInProgress || !navigator.onLine) return;
    
    this.syncInProgress = true;
    
    try {
      const queueItems = await this.getQueueItems();
      
      for (const item of queueItems) {
        try {
          await this.processQueueItem(item);
          await this.removeFromQueue(item.id);
        } catch (error) {
          console.error('Queue item processing failed:', error);
          await this.handleRetry(item, error);
        }
      }
    } catch (error) {
      console.error('Queue processing error:', error);
    } finally {
      this.syncInProgress = false;
    }
  }

  async processQueueItem(item) {
    switch (item.type) {
      case 'create':
        return await this.createRemoteEntity(item.entity);
      case 'update':
        return await this.updateRemoteEntity(item.entityId, item.changes);
      case 'delete':
        return await this.deleteRemoteEntity(item.entityId);
      default:
        throw new Error(`Unknown operation type: ${item.type}`);
    }
  }

  async handleRetry(item, error) {
    if (item.retries < this.retryDelays.length - 1) {
      const delay = this.retryDelays[item.retries];
      
      setTimeout(async () => {
        item.retries++;
        await this.updateQueueItem(item);
        this.processQueue();
      }, delay);
    } else {
      console.error('Max retries reached for queue item:', item);
      await this.moveToFailedQueue(item, error);
    }
  }

  async getQueueItems() {
    const transaction = this.storage.db.transaction(['syncQueue'], 'readonly');
    const store = transaction.objectStore('syncQueue');
    const index = store.index('priority');
    
    return new Promise((resolve, reject) => {
      const request = index.getAll();
      request.onsuccess = () => {
        // Sort by priority and timestamp
        const sorted = request.result.sort((a, b) => {
          const priorityOrder = { high: 0, normal: 1, low: 2 };
          const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
          return priorityDiff !== 0 ? priorityDiff : a.timestamp - b.timestamp;
        });
        resolve(sorted);
      };
      request.onerror = () => reject(request.error);
    });
  }
}

Offline-First Architecture

Local-First Data Access

javascript
class OfflineFirstDataManager {
  constructor() {
    this.storage = new OfflineStorageManager();
    this.syncManager = new SyncQueueManager(this.storage);
    this.isOnline = navigator.onLine;
    
    window.addEventListener('online', () => {
      this.isOnline = true;
      this.syncManager.processQueue();
    });
    
    window.addEventListener('offline', () => {
      this.isOnline = false;
    });
  }

  async getData(id, options = {}) {
    // Always try local first
    const localData = await this.storage.getEntity(id);
    
    if (!this.isOnline || options.localOnly) {
      return localData;
    }
    
    // If online, try to get fresh data
    try {
      const remoteData = await this.fetchFromServer(id);
      
      if (remoteData) {
        // Update local storage with fresh data
        await this.storage.saveEntity(remoteData);
        return remoteData;
      }
    } catch (error) {
      console.warn('Remote fetch failed, using local data:', error);
    }
    
    // Fallback to local data
    return localData;
  }

  async saveData(id, data, options = {}) {
    // Always save locally first
    const savedData = await this.storage.saveEntity({ id, ...data });
    
    if (this.isOnline && !options.localOnly) {
      try {
        // Try immediate sync
        await this.syncToServer(id, data);
        
        // Mark as synced
        await this.storage.saveEntity({ 
          id, 
          ...data, 
          syncStatus: 'synced',
          lastSynced: Date.now()
        });
      } catch (error) {
        console.warn('Immediate sync failed, queuing for later:', error);
        
        // Queue for later sync
        await this.syncManager.queueOperation({
          type: 'update',
          entityId: id,
          changes: data,
          priority: options.priority || 'normal'
        });
      }
    }
    
    return savedData;
  }

  async deleteData(id, options = {}) {
    // Mark as deleted locally
    await this.storage.saveEntity({ 
      id, 
      deleted: true, 
      syncStatus: 'pending',
      deletedAt: Date.now()
    });
    
    if (this.isOnline && !options.localOnly) {
      try {
        await this.deleteFromServer(id);
        
        // Remove from local storage after successful server delete
        await this.storage.deleteEntity(id);
      } catch (error) {
        console.warn('Immediate delete failed, queuing for later:', error);
        
        await this.syncManager.queueOperation({
          type: 'delete',
          entityId: id,
          priority: options.priority || 'normal'
        });
      }
    }
  }

  async getAllData(type, options = {}) {
    const localData = await this.storage.getEntitiesByType(type);
    
    // Filter out deleted items
    const activeData = localData.filter(item => !item.deleted);
    
    if (!this.isOnline || options.localOnly) {
      return activeData;
    }
    
    // Background refresh from server
    this.refreshFromServer(type).catch(error => {
      console.warn('Background refresh failed:', error);
    });
    
    return activeData;
  }

  async refreshFromServer(type) {
    try {
      const remoteData = await this.fetchListFromServer(type);
      
      // Update local storage with fresh data
      for (const item of remoteData) {
        await this.storage.saveEntity(item);
      }
      
      return remoteData;
    } catch (error) {
      console.error('Server refresh failed:', error);
      throw error;
    }
  }
}

Cross-Platform Considerations

Platform Differences

iOS vs Android Networking

javascript
class PlatformAwareNetworking {
  constructor() {
    this.platform = this.detectPlatform();
    this.networkConfig = this.getPlatformConfig();
  }

  detectPlatform() {
    const userAgent = navigator.userAgent;
    
    if (/iPad|iPhone|iPod/.test(userAgent)) {
      return 'ios';
    } else if (/Android/.test(userAgent)) {
      return 'android';
    } else {
      return 'web';
    }
  }

  getPlatformConfig() {
    switch (this.platform) {
      case 'ios':
        return {
          timeout: 30000, // iOS uygulamaları genelde daha uzun timeout kullanır
          maxConcurrentRequests: 4,
          retryAttempts: 3,
          backgroundSyncEnabled: true,
          tlsVersion: '1.3' // iOS ATS requirements
        };
        
      case 'android':
        return {
          timeout: 20000,
          maxConcurrentRequests: 6,
          retryAttempts: 5,
          backgroundSyncEnabled: true,
          compressionEnabled: true
        };
        
      default:
        return {
          timeout: 15000,
          maxConcurrentRequests: 8,
          retryAttempts: 3,
          backgroundSyncEnabled: false
        };
    }
  }

  async makeRequest(url, options = {}) {
    const platformOptions = {
      ...options,
      timeout: options.timeout || this.networkConfig.timeout
    };

    // Platform-specific headers
    if (this.platform === 'ios') {
      platformOptions.headers = {
        ...platformOptions.headers,
        'User-Agent': this.getIOSUserAgent()
      };
    } else if (this.platform === 'android') {
      platformOptions.headers = {
        ...platformOptions.headers,
        'X-Requested-With': 'XMLHttpRequest'
      };
    }

    return await this.executeRequest(url, platformOptions);
  }

  getIOSUserAgent() {
    // iOS için özel User-Agent
    return `MyApp/1.0 (iOS; ${navigator.platform})`;
  }
}

Flutter Cross-Platform Implementation

dart
class FlutterNetworkManager {
  late Dio _dio;
  late ConnectivityResult _connectionStatus;
  
  FlutterNetworkManager() {
    _initializeDio();
    _initializeConnectivity();
  }
  
  void _initializeDio() {
    _dio = Dio();
    
    // Platform-specific configurations
    if (Platform.isIOS) {
      _dio.options.connectTimeout = Duration(seconds: 30);
      _dio.options.sendTimeout = Duration(seconds: 30);
      _dio.options.receiveTimeout = Duration(seconds: 30);
    } else if (Platform.isAndroid) {
      _dio.options.connectTimeout = Duration(seconds: 20);
      _dio.options.sendTimeout = Duration(seconds: 20);
      _dio.options.receiveTimeout = Duration(seconds: 20);
    }
    
    // Add interceptors
    _dio.interceptors.add(PlatformInterceptor());
    _dio.interceptors.add(RetryInterceptor());
    _dio.interceptors.add(CacheInterceptor());
  }
  
  void _initializeConnectivity() {
    Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
      _connectionStatus = result;
      _handleConnectivityChange(result);
    });
  }
  
  void _handleConnectivityChange(ConnectivityResult result) {
    switch (result) {
      case ConnectivityResult.wifi:
        _enableHighBandwidthFeatures();
        break;
      case ConnectivityResult.mobile:
        _enableDataSavingMode();
        break;
      case ConnectivityResult.none:
        _enableOfflineMode();
        break;
    }
  }
  
  void _enableHighBandwidthFeatures() {
    // WiFi'da yüksek kaliteli content
    _dio.options.extra['imageQuality'] = 'high';
    _dio.options.extra['prefetchEnabled'] = true;
  }
  
  void _enableDataSavingMode() {
    // Mobil data'da optimization
    _dio.options.extra['imageQuality'] = 'medium';
    _dio.options.extra['compressionEnabled'] = true;
    _dio.options.extra['prefetchEnabled'] = false;
  }
  
  void _enableOfflineMode() {
    // Offline mode aktivasyonu
    _dio.options.extra['offlineMode'] = true;
  }
  
  Future<Response> get(String path, {Map<String, dynamic>? queryParameters}) async {
    try {
      return await _dio.get(path, queryParameters: queryParameters);
    } catch (e) {
      return _handleError(e);
    }
  }
  
  Future<Response> post(String path, {dynamic data}) async {
    try {
      return await _dio.post(path, data: data);
    } catch (e) {
      return _handleError(e);
    }
  }
  
  Response _handleError(dynamic error) {
    if (error is DioError) {
      switch (error.type) {
        case DioErrorType.connectTimeout:
        case DioErrorType.sendTimeout:
        case DioErrorType.receiveTimeout:
          throw NetworkTimeoutException();
        case DioErrorType.response:
          throw NetworkResponseException(error.response?.statusCode ?? 0);
        case DioErrorType.other:
          if (_connectionStatus == ConnectivityResult.none) {
            throw NetworkOfflineException();
          }
          throw NetworkUnknownException();
        default:
          throw NetworkUnknownException();
      }
    }
    throw error;
  }
}

class PlatformInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    // Platform-specific headers
    if (Platform.isIOS) {
      options.headers['User-Agent'] = 'MyApp-iOS/1.0';
    } else if (Platform.isAndroid) {
      options.headers['User-Agent'] = 'MyApp-Android/1.0';
    }
    
    super.onRequest(options, handler);
  }
}

Unified Architecture

Shared Networking Layer

javascript
class UnifiedNetworkLayer {
  constructor() {
    this.adapters = {
      web: new WebNetworkAdapter(),
      native: new NativeNetworkAdapter(),
      flutter: new FlutterNetworkAdapter()
    };
    
    this.currentAdapter = this.detectAdapter();
  }

  detectAdapter() {
    if (typeof window !== 'undefined' && window.flutter_inappwebview) {
      return this.adapters.flutter;
    } else if (typeof window !== 'undefined') {
      return this.adapters.web;
    } else {
      return this.adapters.native;
    }
  }

  async request(config) {
    // Unified request interface
    const normalizedConfig = this.normalizeConfig(config);
    return await this.currentAdapter.request(normalizedConfig);
  }

  normalizeConfig(config) {
    return {
      url: config.url,
      method: config.method || 'GET',
      headers: config.headers || {},
      data: config.data,
      timeout: config.timeout || 30000,
      retries: config.retries || 3
    };
  }

  // Common methods that all platforms support
  async get(url, config = {}) {
    return this.request({ ...config, url, method: 'GET' });
  }

  async post(url, data, config = {}) {
    return this.request({ ...config, url, method: 'POST', data });
  }

  async put(url, data, config = {}) {
    return this.request({ ...config, url, method: 'PUT', data });
  }

  async delete(url, config = {}) {
    return this.request({ ...config, url, method: 'DELETE' });
  }
}

// Platform-specific adapters
class WebNetworkAdapter {
  async request(config) {
    const response = await fetch(config.url, {
      method: config.method,
      headers: config.headers,
      body: config.data ? JSON.stringify(config.data) : undefined
    });
    
    return this.normalizeResponse(response);
  }

  async normalizeResponse(response) {
    return {
      status: response.status,
      statusText: response.statusText,
      headers: Object.fromEntries(response.headers.entries()),
      data: await response.json()
    };
  }
}

class NativeNetworkAdapter {
  async request(config) {
    // React Native or native platform implementation
    const response = await fetch(config.url, {
      method: config.method,
      headers: config.headers,
      body: config.data ? JSON.stringify(config.data) : undefined
    });
    
    return this.normalizeResponse(response);
  }

  async normalizeResponse(response) {
    return {
      status: response.status,
      statusText: response.statusText,
      headers: response.headers,
      data: await response.json()
    };
  }
}

Bu mobile-specific considerations, modern mobile uygulamaların network performansını ve kullanıcı deneyimini optimize etmek için kritik öneme sahiptir. Battery optimization, offline support ve cross-platform compatibility, başarılı bir mobile uygulama için temel gereksinimlerdir.

Eren Demir tarafından oluşturulmuştur.