2015-08-11 8 views
5

Ho trovato una perdita di memoria in Android 5.x Camera2 API che ho anche reported. Il problema è quando si utilizza il dispositivo Android Lollipop che ha implementato l'API Camera2 nella modalità LEGACY. Su tali dispositivi, chiamando lo context.getSystemService(Context.CAMERA_SERVICE) si deve conservare context in modo che non venga raccolto.Come evitare perdite di memoria in context.getSystemService (Context.CAMERA_SERVICE)?

Se questo context è un'attività avviata più volte, è possibile ritrovarsi con riferimenti sospesi a dozzine di istanze dell'attività che non vengono mai raccolte.

Il problema sembra avvenire solo su dispositivi che hanno lecca Camera2 API implementata in LEGACY modalità (ad esempio HTC One M8, Samsung Galaxy S4), mentre non avviene sul Samsung Galaxy S6 che implementa Camera2 API in modalità FULL.

Per dimostrare il problema, ho creato uno small demo app. L'app contiene due attività: la prima contiene un pulsante che chiama la seconda attività. La seconda attività ottiene lo CameraManager e interroga il livello di supporto API Camera2 per la prima fotocamera posteriore e restituisce il risultato alla prima attività. Se si esegue l'applicazione sul dispositivo che implementa Camera2 API in modalità LEGACY, dopo aver toccato il pulsante 98 volte, causando GC e poi il dumping hprof si vedrà esattamente 98 casi dal vivo di Main2Activity, come questo http://www.pohrani.com/f/1H/gs/4EFlHKoj/sgs4.png

Se fate la stessa sul dispositivo che implementa l'API Camera2 nella modalità FULL, vedrai 0 istanze live di Main2Activity, ad esempio http://www.pohrani.com/f/2q/bV/4srUZIJL/sgs6.png

C'è un modo per aggirare questa perdita?

Si potrebbe chiedere perché sto facendo questo? Nella nostra azienda, stiamo sviluppando barcode and OCR scanning solutions e anche un famoso PhotoMath app. Quindi abbiamo un'attività di scansione che controlla la fotocamera e il processo di scansione. Durante l'avvio, l'attività verifica se il dispositivo supporta l'API Camera2 nella modalità FULL o LIMITED e tenta di utilizzarlo per prestazioni migliori, mentre se l'API Camera2 è nella modalità LEGACY, allora preferiamo utilizzare la gestione della fotocamera utilizzando la vecchia API della fotocamera, come facciamo dispositivi pre-Lollipop.

A causa della perdita di memoria menzionata, ogni volta che un client che ha integrato il nostro SDK nella sua app avvia l'attività di scansione, esegue una scansione e ottiene il risultato, un'istanza dell'attività di scansione sarà trapelata a causa del bug. Se il client esegue la scansione molto, questo può consumare più di 20 MB di memoria - un problema serio!

Quindi se qualcuno sa come risolvere questo problema, sarò eternamente grato!

risposta

5

C'è un modo per aggirare questa perdita?

È possibile chiamare getSystemService() sul numerosingleton. Così, invece di:

getSystemService(CAMERA_SERVICE) 

si usa:

getApplicationContext().getSystemService(CAMERA_SERVICE) 

Se la valutazione è corretta, allora questo farà sì che questi riferimenti aggiuntivi per essere agli attuali Application Singleton, che è sempre in giro in processi. E 'effettivamente "pre-filtrato", e non si può perdere ulteriormente avendo più riferimenti ad esso.

+0

Stavo per pubblicare la stessa risposta :) –

+0

Ottima idea! Funziona come un fascino :-) – DoDo

1

Questo è un bug di Android corretto in L MR1.

Fondamentalmente, CameraManager ha mantenuto un riferimento al contesto con cui è stato creato e quindi connesso al servizio fotocamera. Questa connessione ha tenuto in vita l'istanza del gestore di telecamere a tempo indeterminato, e quindi ha mantenuto il Contesto in vita indefinitamente.

Questo è stato corretto in L MR1 per consentire correttamente il recupero degli oggetti di CameraManager quando non si fa più riferimento.