Vista web de Android lenta

174

Mis android webviewsson lentos. Esto está en todo, desde teléfonos hasta 3.0+tabletas con especificaciones más que adecuadas

Sé que se supone que las vistas web son "limitadas", pero veo aplicaciones web hechas con brecha telefónica que deben estar usando todo tipo de CSS3y JQueryhechicería, funcionan bien y rápido

así que me falta algo, ¿hay algún tipo de myWebview.SPEEDHACK(1)eso que pueda usar para acelerar las cosas?

Además, a veces el contenido de mi webview simplemente no se carga, en lugar de cargar lentamente, simplemente no se carga. El activo con el que estoy probando se almacena localmente, sin errores.

CQM
fuente
3
Parece que necesitas publicar un código.
Jasoneer
1
posible duplicado del rendimiento
Ken White
1
@KenWhite, excepto que esta pregunta tiene más respuestas, esta pregunta tiene respuestas mejores y más completas, esta pregunta tiene el doble de puntos de vista, ambas preguntas tienen más de dos años, la versión de Android a la que se aplicaron estas dos preguntas es obsoleta ... ¿qué? ¿exactamente sales de marcar esto?
CQM
@CQM: Esta pregunta fue marcada automáticamente por el sistema debido a la respuesta duplicada de George Mays a continuación. Si su respuesta puede repetirse literalmente como la respuesta a múltiples publicaciones, una de ellas es un duplicado de la otra. La pregunta vinculada se publicó (y respondió) primero en función de la fecha de publicación. Un duplicado es un duplicado, y la primera publicación fue la original (y las respuestas también fueron anteriores). No obtengo nada de señalar esto (y no lo hice en primer lugar).
Ken White
1
Además, no use el evento de clic en sus aplicaciones, agrega un retraso de 300 ms para responder en cada clic, para determinar que es un clic. Mejor usar touchstart en su lugar. He creado un controlador de clics que usa dos eventos y toma el primer evento activado. Utilizo 'clic de inicio táctil', por lo que también funciona sin pantalla táctil.
Codebeat

Respuestas:

132

Depende de la aplicación web que se esté cargando. Pruebe algunos de los siguientes enfoques:

Establezca una mayor prioridad de procesamiento (en desuso de API 18+):

webview.getSettings().setRenderPriority(RenderPriority.HIGH);

Activar / desactivar la aceleración de hardware:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    // chromium, enable hardware acceleration
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
    // older android version, disable hardware acceleration
    webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Deshabilite el caché (si tiene problemas con su contenido):

webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
peceps
fuente
46
Entiendo por qué establecer la prioridad de representación en alta lo haría más rápido. pero ¿por qué apagar el caché?
Dimas Kotvan
39
El método setRederPriority está en desuso, consulte developer.android.com/reference/android/webkit/WebSettings.html
Victor Ionescu
66
Enlace correcto para setRenderPriority está aquí
Christopher Perry
2
¿Dónde pongo este código en mi aplicación? Por favor ayuda - Tengo el mismo problema en WebView de misión crítica
Levchik
66
¿Por qué apagas el caché?
Hassy31
52

Agregar esto android:hardwareAccelerated="true"en el manifiesto fue lo único que mejoró significativamente el rendimiento para mí

Más información aquí: http://developer.android.com/guide/topics/manifest/application-element.html#hwaccel

Remitente
fuente
1
Esto es solo para API v11 / Android
3.xy
66
Tenga cuidado, hay un WebView acelerado por hardware relacionado con errores abiertos, como se indica en la pregunta stackoverflow.com/q/17059899/225341
Victor Ionescu
1
He notado que desactivar la aceleración de hardware en realidad hace que mi aplicación sea más rápida. Con android:hardwareAccelerated="true"CSS, las animaciones 3D tuvieron largas demoras antes de comenzar, el desplazamiento de DIV dentro de otros DIV desplazables no funcionó, y la aplicación era más inestable.
Ernests Karlsons
1
el valor predeterminado es "verdadero" si ha configurado minSdkVersion o targetSdkVersion en "14" o superior;
Vihaan Verma
37

La solución para nosotros fue lo contrario. Deshabilitamos la aceleración de hardware solo en WebView (en lugar de en toda la aplicación en el manifiesto) usando este código:

if (Build.VERSION.SDK_INT >= 11){
    webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Las animaciones CSS3 son más suaves ahora. Estamos usando Android 4.0.

Más información aquí: https://code.google.com/p/android/issues/detail?id=17352

Ena
fuente
44
Desafortunadamente, esto también impide que el componente de video html5 funcione = /
Ja͢ck
No me di cuenta. Utilizamos una vista de video para reproducir videos: afortunadamente solo necesitábamos un video de pantalla completa. Como solución alternativa, es posible tener la vista web transparente y una vista de video en segundo plano, aunque sé que no es lo mismo.
Ena
1
Hay otro problema con esta solución. Al tocar la vista web, el gráfico se distorsiona un poco. Por ejemplo, si tiene una imagen con un círculo, notará pequeños cuadrados (píxeles) en lugar de la línea suave. Puedo decir que con Android 4.3 la solución es inútil, no tiene problemas de rendimiento.
Ena
Lo siento un poco nuevo para Android. ¿Se puede pegar directamente en el manifiesto de Android, ya que el archivo de manifiesto es XML? ¿O se supone que esto se valida en el código fuente al cargar la vista web? Perdón por la pregunta novata.
xMythicx
1
Después de agregar, obteniendo este errorWebView not displayed because it is too large to fit into a software layer (or drawing cache), needs 11534400 bytes, only 8294400 available
developer1011
14

Creo que lo siguiente funciona mejor:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
    webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Android 19 tiene un motor Chromium para WebView. Supongo que funciona mejor con la aceleración de hardware.

Tedi
fuente
1
Esto funcionó para mí en WebViews con animaciones y desplazamiento pobres
cal
¿Soy yo o tu 'otro' hace lo mismo que tu 'si'?
Codebeat
Erwinus uno es para type_SOFTWARE y el otro Hardware
user2582318
9

Estaba teniendo este mismo problema y tuve que resolverlo. Probé estas soluciones, pero al final el rendimiento, al menos para el desplazamiento, no mejoró en absoluto. Así que aquí el trabajo que realicé y la explicación de por qué funcionó para mí.

Si tuvo la oportunidad de explorar los eventos de arrastre, solo un poco, creando una clase "MiWebView", sobrescribiendo el método "onTouchEvent" y al menos imprimió la hora en que ocurre cada evento de arrastre, verá que están separados a tiempo para (hasta) 9ms de distancia. Ese es un tiempo muy corto entre eventos.

Eche un vistazo al código fuente de WebView y solo vea la función onTouchEvent. Es simplemente imposible que el procesador lo maneje en menos de 9 ms (¡Sigue soñando!). Es por eso que constantemente se ve el mensaje "Perder un arrastre mientras esperamos la respuesta de WebCore para el aterrizaje". mensaje. El código simplemente no se puede manejar a tiempo.

¿Como arreglarlo? Primero, no puede volver a escribir el código onTouchEvent para mejorarlo, es demasiado. Pero, puede "burlarse de él" para limitar la tasa de eventos para arrastrar movimientos, digamos a 40 ms o 50 ms. (Esto depende del procesador).

Todos los eventos táctiles son así: ACTION_DOWN -> ACTION_MOVE ...... ACTION_MOVE -> ACTION_UP. Por lo tanto, debemos mantener los movimientos ABAJO y ARRIBA y filtrar la tasa de MOVIMIENTO (estos son los malos).

Y aquí hay una forma de hacerlo (puede agregar más tipos de eventos, como tocar dos dedos, todo lo que me interesa aquí es el desplazamiento con un solo dedo).

import android.content.Context;
import android.view.MotionEvent;
import android.webkit.WebView;


public class MyWebView extends WebView{

    public MyWebView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    private long lastMoveEventTime = -1;
    private int eventTimeInterval = 40;

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        long eventTime = ev.getEventTime();
        int action = ev.getAction();

        switch (action){
            case MotionEvent.ACTION_MOVE: {
                if ((eventTime - lastMoveEventTime) > eventTimeInterval){
                    lastMoveEventTime = eventTime;
                    return super.onTouchEvent(ev);
                }
                break;
            }
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_UP: {
                return super.onTouchEvent(ev);
            }
        }
        return true;
    }
}

Por supuesto, use esta clase en lugar de WebView y verá la diferencia al desplazarse.

Este es solo un enfoque para una solución, pero aún no está completamente implementado para todos los casos de retraso debido al toque de la pantalla cuando se usa WebView. Sin embargo, es la mejor solución que encontré, al menos para mis necesidades específicas.

Nate Castro
fuente
Me gustaría señalar que el código fuente de la vista web que publicó es de 2010
CQM
Esto no funciona, no suaviza el desplazamiento, no puedo sentir la diferencia.
neevek
He implementado esta configuración hasta 80, pero en realidad no parece mejorar el rendimiento, pero capta algunos eventos de movimiento. Que hace por ti?
Ragnar
He leído que un evento de clic es 6 veces más lento que el evento táctil. Para evitar demoras, puede usar $ ('# botón'). On ('touchstart click', function () {action here; return false;});
Codebeat
Además, no use el evento de clic en sus aplicaciones html, agrega un retraso de 300 ms para responder en cada clic, para determinar que es un clic. Mejor usar touchstart en su lugar. He creado un controlador de clics que usa dos eventos y toma el primer evento activado. Utilizo 'clic de inicio táctil', por lo que aún funciona sin una pantalla táctil.
Codebeat
9

Intenté todas las propuestas para solucionar el problema de rendimiento de renderizado en mi aplicación phonegap. Pero nada realmente funcionó.

Finalmente, después de un día entero de búsqueda, lo logré. Lo configuro dentro de la etiqueta (no la etiqueta) de mi AndroidManifest

<application android:hardwareAccelerated="false" ...

Ahora la aplicación se comporta de la misma manera rápida que mi navegador web. Parece que, si la aceleración de hardware no es siempre la mejor característica ...

El problema detallado que tuve: https://stackoverflow.com/a/24467920/3595386

usuario3595386
fuente
2
Desactivar la aceleración de hardware fue horrible para mí, la vista web fue muy lenta en el desplazamiento
AbdelHady
5

Ninguna de esas respuestas no fue útil para mí.

Finalmente encontré razón y solución. La razón fue una gran cantidad de filtros CSS3 (filter, -webkit-filter).

Solución

He agregado la detección de WebView en el script de la página web para agregar la clase "baja calidad" al cuerpo HTML. Por cierto. Puede rastrear fácilmente WebView configurando el agente de usuario en la configuración de WebView. Luego creé una nueva regla CSS

body.lowquality * { filter: none !important; }
l00k
fuente
Incómodo cuando 5 años después hay muy pocas razones para usar la vista web a pesar de que los dispositivos son más rápidos, el rendimiento del navegador móvil ha mejorado mucho y otras razones. ¡Gracias por investigarlo!
CQM
@CQM Tuve el mismo problema, encontré la solución, así que quería compartirlo :)
l00k
Solo estoy siendo gracioso, esta es una de mis preguntas más antiguas, ¡gracias de nuevo!
CQM
1
Es absurdo que este sea un problema en 2016/2017. Ninguno de los filtros CSS debería ser un desafío para ninguna GPU móvil.
Adam Leggett
4

Si solo hay unos pocos componentes de su vista web que son lentos o lentos, intente agregar esto a los elementos css:

transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);

Este ha sido el único speedhack que realmente tuvo un efecto en mi webview. ¡Pero tenga cuidado de no usarlo en exceso! (puedes leer más sobre el hack en este artículo ).

Erex
fuente
1
Uso will-change: transform.
Adam Leggett
3

Prueba esto:

mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
George Maisuradze
fuente
3

Si está vinculado al onclickevento, puede ser lento en las pantallas táctiles.

Para hacerlo más rápido, utilizo fastclick , que utiliza los eventos táctiles mucho más rápidos para imitar el evento de clic.

Tzach
fuente
fastclick ya no se está desarrollando ... sí, los eventos táctiles son lentos y solo necesitaba que funcionara y descubrí que con jquery se puede solucionar el problema de la velocidad $('#').on('touchstart', function() {...});en lugar de onclick
CrandellWS