Nesne Yaşam Döngüsü Yönetimi (Object Lifecycle Management)
Mobil uygulamalarda nesne yaşam döngüsü yönetimi, bellek sızıntılarını önlemek ve performansı optimize etmek için kritik öneme sahiptir.
Singleton ve Scoped Nesneler
Akıllı Singleton Yönetimi
java
// Android - Yaşam Döngüsüne Duyarlı Akıllı Singleton
public class SmartSingleton {
private static volatile SmartSingleton INSTANCE;
private final Map<String, Object> cache = new ConcurrentHashMap<>();
private final Set<LifecycleObserver> observers = new ConcurrentHashMap<>();
private boolean isApplicationInBackground = false;
public static SmartSingleton getInstance() {
if (INSTANCE == null) {
synchronized (SmartSingleton.class) {
if (INSTANCE == null) {
INSTANCE = new SmartSingleton();
}
}
}
return INSTANCE;
}
private SmartSingleton() {
// Uygulama yaşam döngüsü gözlemcisi
ProcessLifecycleOwner.get().getLifecycle().addObserver(new DefaultLifecycleObserver() {
@Override
public void onStart(@NonNull LifecycleOwner owner) {
isApplicationInBackground = false;
onApplicationForeground();
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
isApplicationInBackground = true;
onApplicationBackground();
}
});
}
public <T> void put(String key, T value, LifecycleOwner lifecycleOwner) {
cache.put(key, value);
// Yaşam döngüsü gözlemcisi ekle
LifecycleObserver observer = new DefaultLifecycleObserver() {
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
cache.remove(key);
observers.remove(this);
owner.getLifecycle().removeObserver(this);
}
};
observers.add(observer);
lifecycleOwner.getLifecycle().addObserver(observer);
}
public <T> T get(String key, Class<T> type) {
Object value = cache.get(key);
return type.isInstance(value) ? type.cast(value) : null;
}
private void onApplicationForeground() {
// Uygulama ön plana geldiğinde
notifyObservers("APP_FOREGROUND");
// Kritik veriyi yeniden yükle
refreshCriticalData();
}
private void onApplicationBackground() {
// Uygulama arka plana geçtiğinde
notifyObservers("APP_BACKGROUND");
// Bellek temizliği
performMemoryCleanup();
}
private void performMemoryCleanup() {
// Kritik olmayan önbellek temizliği
cache.entrySet().removeIf(entry ->
entry.getKey().startsWith("temp_") ||
entry.getKey().startsWith("cache_"));
// Zorla çöp toplama ipucu
System.gc();
}
private void refreshCriticalData() {
// Kritik verileri yenile
for (String key : cache.keySet()) {
if (key.startsWith("critical_")) {
// Yenileme mantığı
refreshData(key);
}
}
}
private void notifyObservers(String event) {
for (LifecycleObserver observer : observers) {
if (observer instanceof SmartSingletonObserver) {
((SmartSingletonObserver) observer).onEvent(event);
}
}
}
}
interface SmartSingletonObserver extends LifecycleObserver {
void onEvent(String event);
}
iOS Scoped Nesne Yönetimi
swift
// iOS - Zayıf Referans ile Scoped Nesne Yöneticisi
class ScopedObjectManager {
private var scopedObjects: [String: WeakBox<AnyObject>] = [:]
private var objectLifecycles: [String: ObjectLifecycle] = [:]
private let queue = DispatchQueue(label: "scoped.objects.queue", attributes: .concurrent)
static let shared = ScopedObjectManager()
private init() {
setupMemoryWarningObserver()
}
func register<T: AnyObject>(_ object: T,
withScope scope: ObjectScope,
identifier: String? = nil) -> String {
let objectId = identifier ?? UUID().uuidString
return queue.sync(flags: .barrier) {
let lifecycle = ObjectLifecycle(scope: scope, creationTime: Date())
scopedObjects[objectId] = WeakBox(object)
objectLifecycles[objectId] = lifecycle
// Scope tabanlı temizlik zamanlaması
scheduleCleanup(for: objectId, scope: scope)
return objectId
}
}
func retrieve<T: AnyObject>(_ identifier: String, type: T.Type) -> T? {
return queue.sync {
guard let weakBox = scopedObjects[identifier],
let object = weakBox.value as? T else {
// Nesne serbest bırakıldı, temizlik
cleanup(identifier)
return nil
}
// Erişim zamanını güncelle
objectLifecycles[identifier]?.recordAccess()
return object
}
}
func cleanup(_ identifier: String) {
queue.async(flags: .barrier) { [weak self] in
self?.scopedObjects.removeValue(forKey: identifier)
self?.objectLifecycles.removeValue(forKey: identifier)
}
}
func cleanupExpiredObjects() {
queue.async(flags: .barrier) { [weak self] in
guard let self = self else { return }
let now = Date()
let expiredIds = self.objectLifecycles.compactMap { (id, lifecycle) -> String? in
if lifecycle.isExpired(at: now) {
return id
}
return nil
}
for id in expiredIds {
self.cleanup(id)
}
}
}
private func scheduleCleanup(for identifier: String, scope: ObjectScope) {
switch scope {
case .session:
// Oturum boyunca tut
break
case .view(let duration):
DispatchQueue.main.asyncAfter(deadline: .now() + duration) { [weak self] in
self?.cleanup(identifier)
}
case .request(let ttl):
DispatchQueue.main.asyncAfter(deadline: .now() + ttl) { [weak self] in
self?.cleanup(identifier)
}
case .manual:
// Manuel temizlik
break
}
}
private func setupMemoryWarningObserver() {
NotificationCenter.default.addObserver(
self,
selector: #selector(handleMemoryWarning),
name: UIApplication.didReceiveMemoryWarningNotification,
object: nil
)
}
@objc private func handleMemoryWarning() {
queue.async(flags: .barrier) { [weak self] in
guard let self = self else { return }
// Bellek baskısına göre temizlik önceliği
let sortedLifecycles = self.objectLifecycles.sorted { (first, second) in
first.value.priority.rawValue > second.value.priority.rawValue
}
// Düşük öncelikli nesneleri kaldır
for (id, lifecycle) in sortedLifecycles.suffix(sortedLifecycles.count / 2) {
if lifecycle.scope.canBeCleanedOnMemoryPressure {
self.cleanup(id)
}
}
}
}
}
class WeakBox<T: AnyObject> {
weak var value: T?
init(_ value: T) {
self.value = value
}
}
enum ObjectScope {
case session
case view(duration: TimeInterval)
case request(ttl: TimeInterval)
case manual
var canBeCleanedOnMemoryPressure: Bool {
switch self {
case .session:
return false
case .view, .request, .manual:
return true
}
}
}
class ObjectLifecycle {
let scope: ObjectScope
let creationTime: Date
private(set) var lastAccessTime: Date
private(set) var accessCount: Int = 0
init(scope: ObjectScope, creationTime: Date) {
self.scope = scope
self.creationTime = creationTime
self.lastAccessTime = creationTime
}
func recordAccess() {
lastAccessTime = Date()
accessCount += 1
}
func isExpired(at time: Date) -> Bool {
switch scope {
case .session:
return false
case .view(let duration):
return time.timeIntervalSince(creationTime) > duration
case .request(let ttl):
return time.timeIntervalSince(lastAccessTime) > ttl
case .manual:
return false
}
}
var priority: Priority {
switch scope {
case .session:
return .high
case .view:
return .medium
case .request:
return accessCount > 5 ? .medium : .low
case .manual:
return .high
}
}
}
enum Priority: Int {
case low = 1
case medium = 2
case high = 3
}
Görünüm Yaşam Döngüsü Entegrasyonu
Android Fragment/Activity Yaşam Döngüsü
java
// Android - Görünüm Yaşam Döngüsüne Duyarlı Nesne Yönetimi
public class ViewLifecycleObjectManager {
private final Map<String, ViewScopedCache> viewCaches = new ConcurrentHashMap<>();
public static class ViewScopedCache {
private final Map<String, Object> objects = new ConcurrentHashMap<>();
private final String viewId;
private final ViewState state;
public ViewScopedCache(String viewId) {
this.viewId = viewId;
this.state = new ViewState();
}
public <T> void put(String key, T object) {
objects.put(key, object);
}
public <T> T get(String key, Class<T> type) {
Object obj = objects.get(key);
return type.isInstance(obj) ? type.cast(obj) : null;
}
public void clear() {
// Kaynakları temizle
for (Object obj : objects.values()) {
if (obj instanceof Closeable) {
try {
((Closeable) obj).close();
} catch (IOException e) {
Log.w("ViewCache", "Kaynağı kapatma başarısız", e);
}
}
}
objects.clear();
}
public ViewState getState() {
return state;
}
}
public void registerFragment(Fragment fragment) {
String fragmentId = fragment.getClass().getSimpleName() + "_" + fragment.hashCode();
ViewScopedCache cache = new ViewScopedCache(fragmentId);
viewCaches.put(fragmentId, cache);
fragment.getLifecycle().addObserver(new DefaultLifecycleObserver() {
@Override
public void onCreate(@NonNull LifecycleOwner owner) {
cache.getState().onCreate();
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
cache.getState().onStart();
}
@Override
public void onResume(@NonNull LifecycleOwner owner) {
cache.getState().onResume();
// Önbellekli nesneleri geri yükle
restoreViewState(cache);
}
@Override
public void onPause(@NonNull LifecycleOwner owner) {
cache.getState().onPause();
// Kritik durumu kaydet
saveViewState(cache);
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
cache.getState().onStop();
// Önemsiz önbelleği temizle
clearNonEssentialCache(cache);
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
cache.getState().onDestroy();
cache.clear();
viewCaches.remove(fragmentId);
owner.getLifecycle().removeObserver(this);
}
});
}
public ViewScopedCache getCacheForView(String viewId) {
return viewCaches.get(viewId);
}
private void restoreViewState(ViewScopedCache cache) {
// Görünüm tekrar görünür olduğunda durumu geri yükle
if (cache.getState().wasBackgrounded()) {
// Arka plandan gelen görünüm'ler için önbellek ısıtma
performCacheWarming(cache);
}
}
private void saveViewState(ViewScopedCache cache) {
// Kritik durumu kalıcı hale getir
for (Map.Entry<String, Object> entry : cache.objects.entrySet()) {
if (entry.getValue() instanceof Serializable &&
entry.getKey().startsWith("critical_")) {
saveToPersistedStorage(entry.getKey(), entry.getValue());
}
}
}
private void clearNonEssentialCache(ViewScopedCache cache) {
// Önemsiz önbelleği temizle
cache.objects.entrySet().removeIf(entry ->
!entry.getKey().startsWith("critical_") &&
!entry.getKey().startsWith("essential_"));
}
private void performCacheWarming(ViewScopedCache cache) {
// Asenkron önbellek ısıtma
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
// Beklenen verileri önceden yükle
loadExpectedData(cache);
return null;
}
}.execute();
}
}
class ViewState {
private boolean created = false;
private boolean started = false;
private boolean resumed = false;
private boolean paused = false;
private boolean stopped = false;
private boolean destroyed = false;
private long lastPauseTime = 0;
public void onCreate() { created = true; }
public void onStart() { started = true; }
public void onResume() {
resumed = true;
paused = false;
}
public void onPause() {
paused = true;
resumed = false;
lastPauseTime = System.currentTimeMillis();
}
public void onStop() { stopped = true; started = false; }
public void onDestroy() { destroyed = true; }
public boolean wasBackgrounded() {
return lastPauseTime > 0 &&
(System.currentTimeMillis() - lastPauseTime) > 5000; // 5 saniye
}
public boolean isActive() {
return created && started && resumed && !destroyed;
}
}
iOS View Controller Yaşam Döngüsü
swift
// iOS - UIViewController Yaşam Döngüsüne Duyarlı Nesne Yönetimi
class ViewControllerObjectManager {
private var viewControllerCaches: [String: ViewControllerCache] = [:]
private let queue = DispatchQueue(label: "viewcontroller.cache.queue", attributes: .concurrent)
static let shared = ViewControllerObjectManager()
func register<T: UIViewController>(_ viewController: T) -> String {
let vcId = "\(type(of: viewController))_\(ObjectIdentifier(viewController).hashValue)"
return queue.sync(flags: .barrier) {
let cache = ViewControllerCache(viewController: viewController)
viewControllerCaches[vcId] = cache
setupLifecycleObservers(for: viewController, cacheId: vcId)
return vcId
}
}
func getCache(for viewControllerId: String) -> ViewControllerCache? {
return queue.sync {
return viewControllerCaches[viewControllerId]
}
}
private func setupLifecycleObservers<T: UIViewController>(for viewController: T, cacheId: String) {
// Method swizzling kullanarak yaşam döngüsü methodlarını gözlemle
let originalViewDidLoad = viewController.viewDidLoad
let originalViewWillAppear = viewController.viewWillAppear
let originalViewDidAppear = viewController.viewDidAppear
let originalViewWillDisappear = viewController.viewWillDisappear
let originalViewDidDisappear = viewController.viewDidDisappear
// ViewDidLoad override
let viewDidLoadBlock: @convention(block) (T) -> Void = { [weak self] vc in
originalViewDidLoad()
self?.handleViewDidLoad(cacheId: cacheId)
}
// ViewWillAppear override
let viewWillAppearBlock: @convention(block) (T, Bool) -> Void = { [weak self] vc, animated in
originalViewWillAppear(animated)
self?.handleViewWillAppear(cacheId: cacheId)
}
// ViewDidAppear override
let viewDidAppearBlock: @convention(block) (T, Bool) -> Void = { [weak self] vc, animated in
originalViewDidAppear(animated)
self?.handleViewDidAppear(cacheId: cacheId)
}
// ViewWillDisappear override
let viewWillDisappearBlock: @convention(block) (T, Bool) -> Void = { [weak self] vc, animated in
originalViewWillDisappear(animated)
self?.handleViewWillDisappear(cacheId: cacheId)
}
// ViewDidDisappear override
let viewDidDisappearBlock: @convention(block) (T, Bool) -> Void = { [weak self] vc, animated in
originalViewDidDisappear(animated)
self?.handleViewDidDisappear(cacheId: cacheId)
}
// Method değiştirme mantığını burada uygula
// (Method swizzling uygulaması burada yer alacak)
}
private func handleViewDidLoad(cacheId: String) {
queue.async(flags: .barrier) { [weak self] in
self?.viewControllerCaches[cacheId]?.setState(.loaded)
}
}
private func handleViewWillAppear(cacheId: String) {
queue.async(flags: .barrier) { [weak self] in
guard let cache = self?.viewControllerCaches[cacheId] else { return }
cache.setState(.willAppear)
// Önbellek ısıtma için görünüm görünmeden önce
self?.performPreloadTasks(for: cache)
}
}
private func handleViewDidAppear(cacheId: String) {
queue.async(flags: .barrier) { [weak self] in
self?.viewControllerCaches[cacheId]?.setState(.didAppear)
}
}
private func handleViewWillDisappear(cacheId: String) {
queue.async(flags: .barrier) { [weak self] in
guard let cache = self?.viewControllerCaches[cacheId] else { return }
cache.setState(.willDisappear)
// Kritik durumu kaydet
self?.saveViewControllerState(cache)
}
}
private func handleViewDidDisappear(cacheId: String) {
queue.async(flags: .barrier) { [weak self] in
guard let cache = self?.viewControllerCaches[cacheId] else { return }
cache.setState(.didDisappear)
// Bellek temizliği
self?.performMemoryCleanup(for: cache)
}
}
private func performPreloadTasks(for cache: ViewControllerCache) {
// Görünüm görünmeden önce gerekli verileri önceden yükle
cache.performPreloadTasks()
}
private func saveViewControllerState(_ cache: ViewControllerCache) {
// Kritik durumu UserDefaults veya Core Data'ya kaydet
cache.saveCriticalState()
}
private func performMemoryCleanup(for cache: ViewControllerCache) {
// Önemsiz önbelleği temizle
cache.clearNonEssentialCache()
}
}
class ViewControllerCache {
private weak var viewController: UIViewController?
private var objects: [String: Any] = [:]
private var state: ViewControllerState = .initialized
private let creationTime = Date()
init(viewController: UIViewController) {
self.viewController = viewController
}
func set<T>(_ object: T, forKey key: String, essential: Bool = false) {
let wrappedObject = CachedObject(value: object, isEssential: essential)
objects[key] = wrappedObject
}
func get<T>(forKey key: String, type: T.Type) -> T? {
guard let cachedObject = objects[key] as? CachedObject<T> else {
return nil
}
return cachedObject.value
}
func setState(_ newState: ViewControllerState) {
state = newState
}
func performPreloadTasks() {
// View controller'a özgü önceden yükleme mantığı
DispatchQueue.global(qos: .utility).async { [weak self] in
// Asenkron önceden yükleme işlemleri
self?.preloadExpectedData()
}
}
func saveCriticalState() {
let essentialObjects = objects.compactMapValues { obj -> Any? in
if let cachedObj = obj as? CachedObjectProtocol, cachedObj.isEssential {
return cachedObj.getValue()
}
return nil
}
if !essentialObjects.isEmpty {
let vcIdentifier = viewController?.restorationIdentifier ?? "unknown"
UserDefaults.standard.set(essentialObjects, forKey: "cached_state_\(vcIdentifier)")
}
}
func clearNonEssentialCache() {
objects = objects.compactMapValues { obj in
if let cachedObj = obj as? CachedObjectProtocol, cachedObj.isEssential {
return obj
}
return nil
}
}
private func preloadExpectedData() {
// View controller türüne göre beklenen verileri önceden yükle
guard let vc = viewController else { return }
switch vc {
case is UITableViewController:
preloadTableViewData()
case is UICollectionViewController:
preloadCollectionViewData()
default:
break
}
}
private func preloadTableViewData() {
// TableView için veri önceden yükleme
}
private func preloadCollectionViewData() {
// CollectionView için veri önceden yükleme
}
}
enum ViewControllerState {
case initialized
case loaded
case willAppear
case didAppear
case willDisappear
case didDisappear
case deallocated
}
protocol CachedObjectProtocol {
var isEssential: Bool { get }
func getValue() -> Any
}
struct CachedObject<T>: CachedObjectProtocol {
let value: T
let isEssential: Bool
let creationTime = Date()
func getValue() -> Any {
return value
}
}
Bellek Baskısı Yönetimi
Flutter Bellek Yönetimi
dart
// Flutter - Gelişmiş Bellek Yönetimi
class FlutterMemoryManager {
static final FlutterMemoryManager _instance = FlutterMemoryManager._internal();
factory FlutterMemoryManager() => _instance;
FlutterMemoryManager._internal();
final Map<String, ScopedObjectContainer> _scopedContainers = {};
final List<MemoryPressureObserver> _observers = [];
late final StreamSubscription<AppLifecycleState> _lifecycleSubscription;
void initialize() {
// Uygulama yaşam döngüsü izleme
_lifecycleSubscription = WidgetsBinding.instance.lifecycleStateChanges.listen(
(AppLifecycleState state) {
_handleAppLifecycleChange(state);
},
);
// Bellek baskısı izleme (platforma özgü)
_setupMemoryPressureMonitoring();
}
String createScope(String scopeName, {Duration? ttl, int? maxObjects}) {
final scopeId = '${scopeName}_${DateTime.now().millisecondsSinceEpoch}';
_scopedContainers[scopeId] = ScopedObjectContainer(
scopeId: scopeId,
scopeName: scopeName,
ttl: ttl,
maxObjects: maxObjects ?? 100,
);
return scopeId;
}
void putObject<T>(String scopeId, String key, T object, {bool essential = false}) {
final container = _scopedContainers[scopeId];
if (container != null) {
container.put(key, object, essential: essential);
}
}
T? getObject<T>(String scopeId, String key) {
final container = _scopedContainers[scopeId];
return container?.get<T>(key);
}
void destroyScope(String scopeId) {
final container = _scopedContainers.remove(scopeId);
container?.dispose();
}
void addMemoryPressureObserver(MemoryPressureObserver observer) {
_observers.add(observer);
}
void removeMemoryPressureObserver(MemoryPressureObserver observer) {
_observers.remove(observer);
}
void _handleAppLifecycleChange(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.paused:
_handleAppPaused();
break;
case AppLifecycleState.resumed:
_handleAppResumed();
break;
case AppLifecycleState.detached:
_handleAppDetached();
break;
case AppLifecycleState.inactive:
break;
case AppLifecycleState.hidden:
break;
}
}
void _handleAppPaused() {
// Uygulama arka plana geçtiğinde bellek temizliği
_performMemoryCleanup(MemoryPressureLevel.moderate);
}
void _handleAppResumed() {
// Uygulama ön plana geldiğinde önbellek ısıtma
_performCacheWarming();
}
void _handleAppDetached() {
// Uygulama sonlandığında tüm scope'ları temizle
for (final container in _scopedContainers.values) {
container.dispose();
}
_scopedContainers.clear();
}
void _setupMemoryPressureMonitoring() {
// Platforma özgü bellek baskısı izleme
if (Platform.isAndroid) {
_setupAndroidMemoryMonitoring();
} else if (Platform.isIOS) {
_setupiOSMemoryMonitoring();
}
}
void _setupAndroidMemoryMonitoring() {
// Android ComponentCallbacks2 simülasyonu
Timer.periodic(const Duration(seconds: 30), (timer) {
_checkMemoryUsage();
});
}
void _setupiOSMemoryMonitoring() {
// iOS bellek uyarısı simülasyonu
Timer.periodic(const Duration(seconds: 20), (timer) {
_checkMemoryUsage();
});
}
void _checkMemoryUsage() {
// Basit bellek kullanımı tahmini
final totalObjects = _scopedContainers.values
.map((c) => c.objectCount)
.fold(0, (sum, count) => sum + count);
MemoryPressureLevel level;
if (totalObjects > 1000) {
level = MemoryPressureLevel.critical;
} else if (totalObjects > 500) {
level = MemoryPressureLevel.moderate;
} else {
level = MemoryPressureLevel.normal;
}
if (level != MemoryPressureLevel.normal) {
_handleMemoryPressure(level);
}
}
void _handleMemoryPressure(MemoryPressureLevel level) {
// Gözlemcileri bilgilendir
for (final observer in _observers) {
observer.onMemoryPressure(level);
}
// Otomatik temizlik
_performMemoryCleanup(level);
}
void _performMemoryCleanup(MemoryPressureLevel level) {
switch (level) {
case MemoryPressureLevel.moderate:
_cleanupNonEssentialObjects();
break;
case MemoryPressureLevel.critical:
_cleanupNonEssentialObjects();
_cleanupOldScopes();
break;
case MemoryPressureLevel.normal:
break;
}
}
void _cleanupNonEssentialObjects() {
for (final container in _scopedContainers.values) {
container.clearNonEssential();
}
}
void _cleanupOldScopes() {
final now = DateTime.now();
final scopesToRemove = <String>[];
for (final entry in _scopedContainers.entries) {
if (entry.value.shouldBeCleanedUp(now)) {
scopesToRemove.add(entry.key);
}
}
for (final scopeId in scopesToRemove) {
destroyScope(scopeId);
}
}
void _performCacheWarming() {
// Kritik scope'lar için önbellek ısıtma
for (final container in _scopedContainers.values) {
if (container.scopeName.contains('critical')) {
container.performCacheWarming();
}
}
}
void dispose() {
_lifecycleSubscription.cancel();
for (final container in _scopedContainers.values) {
container.dispose();
}
_scopedContainers.clear();
_observers.clear();
}
}
class ScopedObjectContainer {
final String scopeId;
final String scopeName;
final Duration? ttl;
final int maxObjects;
final DateTime creationTime = DateTime.now();
final Map<String, ScopedObject> _objects = {};
ScopedObjectContainer({
required this.scopeId,
required this.scopeName,
this.ttl,
required this.maxObjects,
});
void put<T>(String key, T object, {bool essential = false}) {
// LRU dışlama
if (_objects.length >= maxObjects) {
_evictLRU();
}
_objects[key] = ScopedObject(
value: object,
isEssential: essential,
creationTime: DateTime.now(),
);
}
T? get<T>(String key) {
final scopedObject = _objects[key];
if (scopedObject == null) return null;
// TTL kontrolü
if (ttl != null && scopedObject.isExpired(ttl!)) {
_objects.remove(key);
return null;
}
// Erişim zamanını güncelle
scopedObject.updateAccess();
return scopedObject.value as T?;
}
void clearNonEssential() {
_objects.removeWhere((key, obj) => !obj.isEssential);
}
bool shouldBeCleanedUp(DateTime now) {
if (ttl == null) return false;
return now.difference(creationTime) > ttl!;
}
void performCacheWarming() {
// Scope'a özgü önbellek ısıtma mantığı
print('Önbellek ısıtma yapılıyor scope: $scopeName');
}
int get objectCount => _objects.length;
void _evictLRU() {
if (_objects.isEmpty) return;
// En az kullanılan önemsiz nesneyi bul
String? lruKey;
DateTime? oldestAccess;
for (final entry in _objects.entries) {
if (!entry.value.isEssential) {
if (oldestAccess == null || entry.value.lastAccessTime.isBefore(oldestAccess)) {
oldestAccess = entry.value.lastAccessTime;
lruKey = entry.key;
}
}
}
if (lruKey != null) {
_objects.remove(lruKey);
}
}
void dispose() {
for (final obj in _objects.values) {
obj.dispose();
}
_objects.clear();
}
}
class ScopedObject {
final dynamic value;
final bool isEssential;
final DateTime creationTime;
DateTime lastAccessTime;
ScopedObject({
required this.value,
required this.isEssential,
required this.creationTime,
}) : lastAccessTime = creationTime;
void updateAccess() {
lastAccessTime = DateTime.now();
}
bool isExpired(Duration ttl) {
return DateTime.now().difference(creationTime) > ttl;
}
void dispose() {
if (value is Sink) {
(value as Sink).close();
} else if (value is StreamSubscription) {
(value as StreamSubscription).cancel();
}
// Gerekirse diğer temizleme mantıkları eklenebilir
}
}
enum MemoryPressureLevel {
normal,
moderate,
critical,
}
abstract class MemoryPressureObserver {
void onMemoryPressure(MemoryPressureLevel level);
}
En İyi Uygulamalar ve Optimizasyon
Nesne Havuzu Deseni
Nesne Havuzu Uygulaması
java
// Android - Nesne Havuzu Uygulaması
public class ObjectPool<T> {
private final Queue<T> pool = new ConcurrentLinkedQueue<>();
private final ObjectFactory<T> factory;
private final int maxPoolSize;
private final AtomicInteger currentSize = new AtomicInteger(0);
public ObjectPool(ObjectFactory<T> factory, int maxPoolSize) {
this.factory = factory;
this.maxPoolSize = maxPoolSize;
}
public T acquire() {
T object = pool.poll();
if (object == null) {
object = factory.create();
} else {
currentSize.decrementAndGet();
}
// Nesne durumunu sıfırla
if (object instanceof Resettable) {
((Resettable) object).reset();
}
return object;
}
public void release(T object) {
if (object == null) return;
if (currentSize.get() < maxPoolSize) {
// Havuzda geri döndürmeden önce nesneyi temizle
if (object instanceof Cleanable) {
((Cleanable) object).clean();
}
pool.offer(object);
currentSize.incrementAndGet();
}
// Eğer havuz doluysa, nesnenin çöp toplayıcı tarafından toplanmasına izin ver
}
public int size() {
return currentSize.get();
}
public void clear() {
T object;
while ((object = pool.poll()) != null) {
if (object instanceof Disposable) {
((Disposable) object).dispose();
}
}
currentSize.set(0);
}
}
interface ObjectFactory<T> {
T create();
}
interface Resettable {
void reset();
}
interface Cleanable {
void clean();
}
interface Disposable {
void dispose();
}
// Örnek kullanım
class BitmapPool extends ObjectPool<Bitmap> {
public BitmapPool(int maxPoolSize) {
super(new BitmapFactory(), maxPoolSize);
}
private static class BitmapFactory implements ObjectFactory<Bitmap> {
@Override
public Bitmap create() {
return Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
}
}
}
Bellek Sızıntısı Tespiti
swift
// iOS - Bellek Sızıntısı Tespiti
class MemoryLeakDetector {
private static var trackedObjects: [WeakObjectWrapper] = []
private static let queue = DispatchQueue(label: "memory.leak.detector")
static func track<T: AnyObject>(_ object: T, file: String = #file, line: Int = #line) {
queue.async {
let wrapper = WeakObjectWrapper(
object: object,
className: String(describing: type(of: object)),
file: file,
line: line,
timestamp: Date()
)
trackedObjects.append(wrapper)
// Serbest bırakılan nesneleri temizle
cleanupDeallocatedObjects()
}
}
static func checkForLeaks() -> [LeakReport] {
return queue.sync {
cleanupDeallocatedObjects()
let now = Date()
let potentialLeaks = trackedObjects.filter { wrapper in
// 60 saniyeden daha eski nesneler potansiyel sızıntı olabilir
now.timeIntervalSince(wrapper.timestamp) > 60
}
return potentialLeaks.map { wrapper in
LeakReport(
className: wrapper.className,
file: wrapper.file,
line: wrapper.line,
age: now.timeIntervalSince(wrapper.timestamp)
)
}
}
}
private static func cleanupDeallocatedObjects() {
trackedObjects = trackedObjects.filter { $0.object != nil }
}
}
private class WeakObjectWrapper {
weak var object: AnyObject?
let className: String
let file: String
let line: Int
let timestamp: Date
init(object: AnyObject, className: String, file: String, line: Int, timestamp: Date) {
self.object = object
self.className = className
self.file = file
self.line = line
self.timestamp = timestamp
}
}
struct LeakReport {
let className: String
let file: String
let line: Int
let age: TimeInterval
var description: String {
return "Potansiyel sızıntı: \(className) \(file):\(line), yaş: \(age)s"
}
}
// Kullanım örneği
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
#if DEBUG
MemoryLeakDetector.track(self)
#endif
}
}
İzleme ve Analitik
Performans Metriği Toplama
dart
// Flutter - Yaşam Döngüsü Performans İzleme
class LifecyclePerformanceMonitor {
static final Map<String, LifecycleMetrics> _metrics = {};
static final List<PerformanceEvent> _events = [];
static void recordObjectCreation(String objectType, {Map<String, dynamic>? metadata}) {
final event = PerformanceEvent(
type: PerformanceEventType.objectCreation,
objectType: objectType,
timestamp: DateTime.now(),
metadata: metadata ?? {},
);
_events.add(event);
_updateMetrics(objectType, event);
}
static void recordObjectDestruction(String objectType, Duration lifetime) {
final event = PerformanceEvent(
type: PerformanceEventType.objectDestruction,
objectType: objectType,
timestamp: DateTime.now(),
metadata: {'lifetime_ms': lifetime.inMilliseconds},
);
_events.add(event);
_updateMetrics(objectType, event);
}
static void recordMemoryPressure(MemoryPressureLevel level, int objectsCleared) {
final event = PerformanceEvent(
type: PerformanceEventType.memoryPressure,
objectType: 'system',
timestamp: DateTime.now(),
metadata: {
'pressure_level': level.toString(),
'objects_cleared': objectsCleared,
},
);
_events.add(event);
}
static LifecycleMetrics? getMetrics(String objectType) {
return _metrics[objectType];
}
static Map<String, dynamic> generateReport() {
final totalObjects = _metrics.values.fold(0, (sum, metrics) => sum + metrics.totalCreated);
final averageLifetime = _calculateAverageLifetime();
final memoryPressureEvents = _events.where((e) => e.type == PerformanceEventType.memoryPressure).length;
return {
'toplam_nesne_oluşturma': totalObjects,
'ortalama_nesne_ömrü_ms': averageLifetime?.inMilliseconds ?? 0,
'bellek_baskısı_olayları': memoryPressureEvents,
'nesne_türü_dağılımı': _metrics.map((type, metrics) => MapEntry(type, {
'oluşturulan': metrics.totalCreated,
'yıkılan': metrics.totalDestroyed,
'ortalama_ömrü_ms': metrics.averageLifetime?.inMilliseconds ?? 0,
'maksimum_ömrü_ms': metrics.maxLifetime?.inMilliseconds ?? 0,
})),
'son_olaylar': _events.take(50).map((e) => e.toMap()).toList(),
};
}
static void _updateMetrics(String objectType, PerformanceEvent event) {
final metrics = _metrics.putIfAbsent(objectType, () => LifecycleMetrics(objectType));
switch (event.type) {
case PerformanceEventType.objectCreation:
metrics.recordCreation();
break;
case PerformanceEventType.objectDestruction:
final lifetimeMs = event.metadata['lifetime_ms'] as int?;
if (lifetimeMs != null) {
metrics.recordDestruction(Duration(milliseconds: lifetimeMs));
}
break;
case PerformanceEventType.memoryPressure:
break;
}
// Sadece son olayları sakla (son 1000)
if (_events.length > 1000) {
_events.removeRange(0, _events.length - 1000);
}
}
static Duration? _calculateAverageLifetime() {
final lifetimes = _metrics.values
.where((m) => m.averageLifetime != null)
.map((m) => m.averageLifetime!.inMilliseconds)
.toList();
if (lifetimes.isEmpty) return null;
final average = lifetimes.fold(0, (sum, lifetime) => sum + lifetime) / lifetimes.length;
return Duration(milliseconds: average.round());
}
}
class LifecycleMetrics {
final String objectType;
int totalCreated = 0;
int totalDestroyed = 0;
Duration? averageLifetime;
Duration? maxLifetime;
final List<Duration> _lifetimes = [];
LifecycleMetrics(this.objectType);
void recordCreation() {
totalCreated++;
}
void recordDestruction(Duration lifetime) {
totalDestroyed++;
_lifetimes.add(lifetime);
// Ortalamayı güncelle
final totalMs = _lifetimes.fold(0, (sum, duration) => sum + duration.inMilliseconds);
averageLifetime = Duration(milliseconds: (totalMs / _lifetimes.length).round());
// Maksimum ömrü güncelle
if (maxLifetime == null || lifetime > maxLifetime!) {
maxLifetime = lifetime;
}
// Sadece son ömürleri sakla
if (_lifetimes.length > 100) {
_lifetimes.removeAt(0);
}
}
}
class PerformanceEvent {
final PerformanceEventType type;
final String objectType;
final DateTime timestamp;
final Map<String, dynamic> metadata;
PerformanceEvent({
required this.type,
required this.objectType,
required this.timestamp,
required this.metadata,
});
Map<String, dynamic> toMap() {
return {
'type': type.toString(),
'object_type': objectType,
'timestamp': timestamp.toIso8601String(),
'metadata': metadata,
};
}
}
enum PerformanceEventType {
objectCreation,
objectDestruction,
memoryPressure,
}
Bu kapsamlı nesne yaşam döngüsü yönetimi stratejileri, mobil uygulamalarda bellek sızıntılarını önler ve optimal performans sağlar. Her platform için özel optimizasyonlar ve izleme araçları kullanarak, uygulama yaşam döngüsü boyunca etkili kaynak yönetimi gerçekleştirir.