Flutter'da Arka Plan Görevleri: WorkManager ve Isolate
Flutter uygulamaları uygulama arka plandayken veya kapalıyken de görev çalıştırabilir. Üç farklı yaklaşım mevcuttur: WorkManager (periyodik ve tek seferlik arka plan görevleri), Dart Isolate (UI thread'i bloke etmeden paralel işlem) ve flutter_background_service (uzun süreli foreground servis).
WorkManager: Periyodik Arka Plan Görevleri
// pubspec: workmanager: ^0.5.2
// main.dart — WorkManager başlatma
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await WorkManager().initialize(
callbackDispatcher,
isInDebugMode: kDebugMode,
);
runApp(const MyApp());
}
// Top-level fonksiyon — ayrı isolate'de çalışır
@pragma('vm:entry-point')
void callbackDispatcher() {
WorkManager().executeTask((taskName, inputData) async {
switch (taskName) {
case 'syncData':
return _syncData(inputData);
case 'cleanCache':
return _cleanCache();
case 'sendAnalytics':
return _sendAnalytics(inputData);
default:
return Future.value(false);
}
});
}
Future<bool> _syncData(Map<String, dynamic>? input) async {
try {
// Flutter bağımlılıkları başlat
final prefs = await SharedPreferences.getInstance();
final token = prefs.getString('auth_token');
if (token == null) return true; // kullanıcı giriş yapmamış
final dio = Dio();
final response = await dio.get(
'https://api.example.com/sync',
options: Options(headers: {'Authorization': 'Bearer $token'}),
);
// Verileri kaydet
await prefs.setString('last_sync', DateTime.now().toIso8601String());
await prefs.setString('sync_data', jsonEncode(response.data));
return true;
} catch (e) {
debugPrint('Senkronizasyon hatası: $e');
return false; // WorkManager görevi başarısız olarak işaretler
}
}
// Görev kaydetme
class BackgroundTaskService {
// Her 15 dakikada bir (minimum interval)
static Future<void> registerPeriodicSync() =>
WorkManager().registerPeriodicTask(
'periodic-sync',
'syncData',
frequency: const Duration(hours: 1),
initialDelay: const Duration(minutes: 5),
constraints: Constraints(
networkType: NetworkType.connected,
requiresBatteryNotLow: true,
),
existingWorkPolicy: ExistingWorkPolicy.replace,
);
// Tek seferlik görev
static Future<void> scheduleOneTimeClean() =>
WorkManager().registerOneOffTask(
'one-off-clean',
'cleanCache',
initialDelay: const Duration(hours: 24),
constraints: Constraints(requiresDeviceIdle: true),
);
// Görevi iptal et
static Future<void> cancelSync() =>
WorkManager().cancelByUniqueName('periodic-sync');
// Tüm görevleri iptal et
static Future<void> cancelAll() => WorkManager().cancelAll();
}
Dart Isolate: UI Thread'i Bloke Etmeden Ağır İşlem
import 'dart:isolate';
// Basit işlemler için compute() yeterli
Future<List<Product>> parseProducts(String json) =>
compute(_parseIsolate, json);
List<Product> _parseIsolate(String json) =>
(jsonDecode(json) as List).map((e) => Product.fromJson(e)).toList();
// Daha kompleks, çift yönlü iletişim için ham Isolate
class ImageProcessingIsolate {
late Isolate _isolate;
late SendPort _sendPort;
final _receivePort = ReceivePort();
final _resultController = StreamController<ProcessedImage>.broadcast();
Stream<ProcessedImage> get results => _resultController.stream;
Future<void> start() async {
_isolate = await Isolate.spawn(_isolateEntry, _receivePort.sendPort);
_sendPort = await _receivePort.first as SendPort;
_receivePort.skip(1).listen((msg) {
if (msg is ProcessedImage) _resultController.add(msg);
});
}
void processImage(Uint8List imageBytes, ImageFilter filter) {
_sendPort.send({'bytes': imageBytes, 'filter': filter.name});
}
void dispose() {
_isolate.kill(priority: Isolate.immediate);
_receivePort.close();
_resultController.close();
}
}
@pragma('vm:entry-point')
void _isolateEntry(SendPort mainSendPort) async {
final receivePort = ReceivePort();
mainSendPort.send(receivePort.sendPort);
await for (final msg in receivePort) {
final map = msg as Map<String, dynamic>;
final bytes = map['bytes'] as Uint8List;
final filterName = map['filter'] as String;
// Ağır görüntü işleme
final processed = await _applyFilter(bytes, ImageFilter.fromName(filterName));
mainSendPort.send(processed);
}
}
// Isolate havuzu — birden fazla paralel görev
class IsolatePool {
final int _size;
final List<IsolateWorker> _workers = [];
int _roundRobin = 0;
IsolatePool(this._size);
Future<void> initialize() async {
for (var i = 0; i < _size; i++) {
final worker = IsolateWorker();
await worker.start();
_workers.add(worker);
}
}
Future<T> run<T>(Future<T> Function() task) {
final worker = _workers[_roundRobin % _size];
_roundRobin++;
return worker.execute(task);
}
}
flutter_background_service: Uzun Süreli Servis
// pubspec: flutter_background_service: ^5.0.5
// main.dart
Future<void> initBackgroundService() async {
final service = FlutterBackgroundService();
await service.configure(
androidConfiguration: AndroidConfiguration(
onStart: onBackgroundServiceStart,
autoStart: false,
isForegroundMode: true, // foreground service — kullanıcıya bildirim gösterir
notificationChannelId: 'background_service',
initialNotificationTitle: 'Uygulama Çalışıyor',
initialNotificationContent: 'Arka planda çalışıyor',
foregroundServiceNotificationId: 888,
),
iosConfiguration: IosConfiguration(
autoStart: false,
onForeground: onBackgroundServiceStart,
onBackground: onIosBackground,
),
);
}
@pragma('vm:entry-point')
Future<bool> onIosBackground(ServiceInstance service) async {
WidgetsFlutterBinding.ensureInitialized();
DartPluginRegistrant.ensureInitialized();
return true;
}
@pragma('vm:entry-point')
void onBackgroundServiceStart(ServiceInstance service) async {
DartPluginRegistrant.ensureInitialized();
if (service is AndroidServiceInstance) {
service.on('setAsForeground').listen((_) =>
service.setAsForegroundService());
service.on('setAsBackground').listen((_) =>
service.setAsBackgroundService());
}
service.on('stopService').listen((_) => service.stopSelf());
// Periyodik işlem
Timer.periodic(const Duration(seconds: 30), (timer) async {
if (service is AndroidServiceInstance &&
!await service.isForegroundService()) {
timer.cancel();
return;
}
// Konum güncelle
final pos = await Geolocator.getCurrentPosition();
service.invoke('locationUpdate', {
'lat': pos.latitude,
'lng': pos.longitude,
'timestamp': DateTime.now().toIso8601String(),
});
// Bildirimi güncelle
service.setForegroundNotificationInfo(
title: 'Takip Aktif',
content: '${pos.latitude.toStringAsFixed(4)}, ${pos.longitude.toStringAsFixed(4)}',
);
});
}
// UI'dan servisi başlatma/durdurma
FloatingActionButton(
onPressed: () async {
final service = FlutterBackgroundService();
if (await service.isRunning()) {
service.invoke('stopService');
} else {
service.startService();
}
},
child: const Icon(Icons.location_on),
)
Arka plan görevleri için doğru aracı seçin: kısa ve periyodik görevler için WorkManager, CPU-yoğun hesaplamalar için Isolate, sürekli çalışan servisler için flutter_background_service. Her üçü de pil optimizasyonuna dikkat eder; gereksiz arka plan işlemlerinden kaçının.