Cómo solucionar el desbordamiento de memoria en la animación de fotogramas de Android
[html]Ver texto sin formato
& lt? versión xml = "1.0" codificación = "utf-8"? & gt
& lt lista de animaciones xmlns:Android = "/apk/RES/Android "
Android:one shot = " true " & gt;
& litem Android:drawable = " @ drawable/a 1 " Android:duration = " 100 " & gt;& lt/item & gt;
& litem Android:drawable = " @ drawable/a2 " Android:duración = " 100 " & gt; & gt;
& litem Android:drawable = " @ drawable/a5 " Android:duración = " 100 " & gt;& lt/item & gt;
& litem Android: drawable = " @ drawable/a6 " Android:duration = " 100 " & gt;& lt/item & gt;
& litem Android:drawable = " @ drawable/a7 " Android:duration = " 100 " & gt;& lt/item & gt;
& litem Android:drawable = " @ drawable/A8 " Android:duration = " 100 " & gt; & lt/item & gt;
& litem Android:drawable = " @ drawable/a9 " Android:duration = " 100 " & gt;& lt/item & gt;
& litem Android:drawable = " @ drawable/ a 10 " Android:duration = " 100 " & gt; & lt/item & gt;
& litem Android:drawable = " @ drawable/a 11 " Android:duration = " 100 " >; & lt/item & gt;
& lt/animation-list & gt;
2. >[java]Ver texto sin formato
search _ scale _ iv . setbackgroundresource(r . drawable . anim _ search
AnimationDrawable drawable =(AnimationDrawable)search _ scale _ iv . get background();
drawable .start();
Por lo tanto, hay un desbordamiento de memoria en setBackgroundResource.
De hecho, este método consume mucha memoria al obtener el elemento de diseño y es propenso a desbordarse y fallar.
3. Solución: encontré una clase en Internet y la solucioné. Como resultado, utilicé 11 imágenes de tamaño 560k y no hubo desbordamiento de memoria;
[java] Ver texto sin formato
Importar contenido de Android;
.Importar contenido de Android. RES. Analizador de recursos XML;
Importar gráficos de Android.
Importar gráficos dibujables de Android. p>Importar gráficos de Android. Dibujables.
Importar gráficos de Android. .widget.imageview;
Importar org.Apache.commons.io.ioutils;
Importar org.xmlpull.v1. XmlPullParser
Importa org.xmlpull.v1. XmlPullParserException
Importar Java io .io excepción;
Importar Java util . >/****
*Esta clase de utilidad se origina en el flujo de desbordamiento de la pila.
*Enlace original:/questions/8692328/error de falta de memoria-en-animación-cuadro-a-cuadro-en-Android.
* El método BitmapFactory.decodeByteArray se utiliza principalmente para dibujar imágenes a través de C subyacente, lo que previene eficazmente OOM.
*Utilice la biblioteca de clases de terceros: org.apache.commons.io.IOUtils para convertir el flujo de entrada en una matriz de bytes.
* *******/
Clase pública MyAnimationDrawable {
Clase estática pública MyFrame {
byte[] palabra sección;
int duración;
dibujable;
boolean isReady = false
}
Interfaz pública de OnDrawableLoadedListener {
public void onDrawableLoaded(List & lt; MyFrame & gtmy frames
}
// 1
/*); **
*Mejor rendimiento
*Establecer tiempo en la lista de animaciones.
* **/
public static void animaterawmanullyfromxml(int ResourceId,
Vista de imagen final, finalmente ejecutable al iniciar,
Finalmente ejecute onComplete) {
loadRaw(resourceId, imageView.getContext(),
new OnDrawableLoadedListener() {
@override
public void onDrawableLoaded(List & lt; MyFrame & gtmyFrames) {
If (onStart!= null) {
onstart run();
}<. /p>
animateRawManually(myFrames, imageView, completo);
}
});
}
/ / 2
Carga vacía estática privadaRaw(final int ResourceId, contexto de contexto final,
final OnDrawableLoadedListener OnDrawableLoadedListener){
loadFromXml(resourceId, contexto, onDrawableLoadedListener);
}
// 3
Carga vacía estática privadaFromXml(final int ResourceId,
Contexto de contexto final,
final OnDrawableLoadedListener OnDrawableLoadedListener){
nuevo hilo(nuevo Runnable() {
@override
public void run(){
Lista de matriz final & ltMyFrame & gtmyFrames = new ArrayList & ltMyFrame & gt();
Analizador de recursos XML = contexto .obtener recursos().
resourceId ; p>
Prueba {
int tipo de evento = parser . get tipo de evento();
mientras (eventType! =XmlPullParser. END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
} else if(event type == XML pull parser.START_TAG) {
if (parser.getName().equals("item")) {
byte[]bytes = null;
int duración = 1000;
for( int I = 0;i<parser.getAttributeCount();i++) {
if (parser.getAttributeName(i)).
es igual(
" dibujable")) {
int resId = Integer.parseInt(parser
.getAttributeValue(i)
. subcadena(1));
bytes = IOUtils.toByteArray(context
.getResources()
.openraw recurso(resId));
p>
} else if(parser . getattributename(I)
. es igual a ("duración"){
duración = parser . getattributeintvalue(
i, 1000);
}
}
mi marco mi marco = nuevo mi marco();
myFrame.bytes = bytes
myFrame.duration =duración;
mis marcos . add(mi marco);
}
} else if (tipo de evento == analizador de extracción XML. END_TAG) {
} else if (tipo de evento == analizador de extracción XML. texto) {
}
tipo de evento = analizador . next();
}
} catch (IOException e) {
e . p> } catch(XmlPullParserException E2){
// TODO: Manejar excepciones
E2 . printstacktrace();
}
// Ejecuta un nuevo controlador (context.getMainLooper()) en el hilo de la interfaz de usuario.
post(new Runnable() {
@override
public void runnable(){
if (onDrawableLoadedListener!= null) {
ondrawableloadedlistener .ondrawableloaded(mis marcos);
}
}
});
}
}).run();
}
// 4
Animador de vacío estático privado manualmente(List<MyFrame>MyFrame,
ImageView imageView, se puede ejecutar onComplete) {
animateRawManually(myFrames, imageView, onComplete, 0);
}
// 5
AnimateRawManually de vacío estático privado (lista final<MyFrame>MyFrame,
Vista de imagen final, ejecutable final completo,
Número de fotograma final){
final mi fotograma este fotograma = mis marcos get(número de fotograma);
if (frameNumber == 0) {
este fotograma dibujable = new BitmapDrawable(imageview. get context()
.getResources(), BitmapFactory.decodeByteArray(
thisFrame.bytes, 0, este marco. bytes. longitud));
p>}En caso contrario {
mi marco marco anterior = mis marcos. get(número de marco-1);
((BitmapDrawable)marco anterior. dibujable). obtener mapa de bits(). recycle();
previousFrame.drawable = null
el marco anterior está listo = false;
}
imageview. este marco. dibujable);
Nuevo controlador().
postDelayed(new Runnable() {
@Override
public void Runnable(){
//Asegúrate de que ImageView no se haya cambiado a una imagen diferente
//En este momento
if(imageview. get drawable()= = este marco. dibujable){
if(número de marco+1 & lt ;myFrames.size()) {
mi fotograma siguiente fotograma = mis fotogramas get(número de fotograma+1);
if (nextFrame.isReady) {
/ /Crear el siguiente cuadro de animación
Manual de animación (myFrames, imageView, onComplete,
número de cuadro+1
} De lo contrario {
el siguiente fotograma está listo = verdadero;
}
}else{
if (onComplete!= null) {
al completar la ejecución();
}
}
}
}
}, duración de este fotograma);
//Carga el siguiente fotograma
if(número de fotograma+1 & lt;myFrames.size()) {
Nuevo hilo( new Runnable() {
@override
public void runnable(){
mi fotograma siguiente fotograma = mis fotogramas. get(número de fotograma +1);
siguiente cuadro . drawable = new BitmapDrawable(imageView
.getContext().getResources(),
bitmapfactory .decodebytearray(siguiente cuadro . bytes, 0,
siguiente fotograma. bytes de longitud));
if (nextFrame.isReady) {
//Crea el siguiente fotograma de animación
Manual de animación(myFrames, imageView, onComplete,
número de fotograma+1
} De lo contrario, {
el siguiente fotograma está listo. = verdadero;
p>
}
}
}).run();
}
}