Affichage Web Android lent

174

Mes android webviewssont lents. C'est sur tout, des téléphones aux 3.0+tablettes avec des spécifications plus que suffisantes

Je sais que webviews sont censés être « limité » mais je vois applications web fait avec espace de téléphone qui doit utiliser toutes sortes de CSS3et la JQuerysorcellerie, ils courent très bien et rapide

donc je manque quelque chose, y a-t-il une sorte de myWebview.SPEEDHACK(1)que je puisse utiliser pour accélérer les choses?

aussi, parfois le contenu de ma vue Web ne se charge tout simplement pas, au lieu de se charger lentement, il ne se charge pas. L'actif avec lequel je teste est stocké localement, sans erreur.

CQM
la source
3
On dirait que vous devez publier du code.
Jasoneer le
1
duplication possible des performances
Ken White
1
@KenWhite sauf que cette question a plus de réponses, cette question a des réponses meilleures et plus complètes, cette question a deux fois plus de vues, les deux questions ont plus de deux ans, la version d'Android à laquelle ces deux questions sont appliquées est obsolète ... quoi est-ce que vous sortez exactement de signaler cela?
CQM
@CQM: Cette question a été signalée automatiquement par le système en raison de la réponse dupliquée de George Mays ci-dessous. Si sa réponse peut être répétée mot pour mot comme réponse à plusieurs messages, l'un d'eux est un double de l'autre. La question liée a été publiée (et répondue) en premier en fonction de la date de publication. Un duplicata est un duplicata, et le premier message était l'original (et les réponses étaient également antérieures). Je n'obtiens rien à signaler cela (et je ne l'ai pas fait en premier lieu).
Ken White
1
De plus, n'utilisez pas l'événement de clic dans vos applications, il ajoute un délai de 300 ms pour répondre à chaque clic, pour déterminer qu'il s'agit d'un clic. Mieux vaut utiliser le touchstart à la place. J'ai créé un gestionnaire de clics qui utilise deux événements et prend le premier événement déclenché. J'utilise 'touchstart click', donc cela fonctionne toujours sans écran tactile.
Codebeat

Réponses:

132

Cela dépend de l'application Web en cours de chargement. Essayez certaines des approches ci-dessous:

Définir une priorité de rendu plus élevée (obsolète à partir de l'API 18+):

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

Activer / désactiver l'accélération matérielle:

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);
}

Désactivez le cache (si vous rencontrez des problèmes avec votre contenu):

webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
peceps
la source
46
Je comprends pourquoi définir la priorité de rendu sur élevé le rendrait plus rapide. mais pourquoi désactiver le cache?
Dimas Kotvan
39
La méthode setRederPriority est obsolète, voir developer.android.com/reference/android/webkit/WebSettings.html
Victor Ionescu
6
Le lien correct pour setRenderPriority est ici
Christopher Perry
2
Où dois-je mettre ce code dans mon application? S'il vous plaît aider - J'ai le même problème sur WebView critique de mission
Levchik
6
pourquoi désactivez-vous le cache?
Hassy31
52

L'ajout de cela android:hardwareAccelerated="true"dans le manifeste était la seule chose qui a considérablement amélioré les performances pour moi

Plus d'informations ici: http://developer.android.com/guide/topics/manifest/application-element.html#hwaccel

Expéditeur
la source
1
Ceci est uniquement pour API v11 / Android 3.x et supérieur
Ludwo
6
Attention, il y a un bug ouvert avec accélération matérielle des WebViews, comme indiqué dans la question stackoverflow.com/q/17059899/225341
Victor Ionescu
1
J'ai remarqué que la désactivation de l'accélération matérielle rend mon application plus rapide. Avec android:hardwareAccelerated="true"CSS, les animations 3D avaient de longs délais avant de commencer, le défilement des DIV dans d'autres DIV défilables ne fonctionnait pas et l'application était plus instable.
Ernests Karlsons
1
la valeur par défaut est "true" si vous avez défini minSdkVersion ou targetSdkVersion sur "14" ou plus;
Vihaan Verma
37

La solution pour nous était le contraire. Nous avons désactivé l'accélération matérielle sur WebView uniquement (plutôt que sur l'ensemble de l'application dans le manifeste) en utilisant ce code:

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

Les animations CSS3 sont désormais plus fluides. Nous utilisons Android 4.0.

Plus d'informations ici: https://code.google.com/p/android/issues/detail?id=17352

Ena
la source
4
Malheureusement, cela empêche également le composant vidéo html5 de fonctionner = /
Ja͢ck
Je n'ai pas remarqué. Nous avons utilisé une vue vidéo pour lire des vidéos: heureusement, nous avions juste besoin d'une vidéo en plein écran. Pour contourner le problème, il est possible d'avoir la vue Web transparente et une vue vidéo en arrière-plan, même si je sais que ce n'est pas la même chose.
Ena
1
Il y a un autre problème avec ce correctif. En touchant la vue Web, le graphique est un peu déformé. Par exemple, si vous avez une image avec un cercle, vous remarquerez des petits carrés (pixels) dessus au lieu de la ligne lisse. Je peux dire qu'avec Android 4.3, le correctif est inutile, il n'a pas de problèmes de performances.
Ena
Désolé un peu nouveau sur Android. Est-ce que cela peut être collé directement dans le manifeste Android étant que le fichier manifeste est XML. Ou est-ce censé être validé dans le code source lors du chargement de la vue Web. Désolé pour la question noob.
xMythicx
1
Après avoir ajouté, obtenir cette erreurWebView not displayed because it is too large to fit into a software layer (or drawing cache), needs 11534400 bytes, only 8294400 available
developer1011
14

Je pense que ce qui suit fonctionne le mieux:

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 a le moteur Chromium pour WebView. Je suppose que cela fonctionne mieux avec l'accélération matérielle.

Tedi
la source
1
Cela a fonctionné pour moi sur les WebViews avec des animations et un défilement médiocres
calibre
Est-ce moi ou est-ce que votre «autre» fait la même chose que votre «si»?
Codebeat
Erwinus one est pour type_SOFTWARE et l'autre matériel
user2582318
9

J'avais ce même problème et je devais le résoudre. J'ai essayé ces solutions, mais à la fin les performances, du moins pour le défilement ne se sont pas améliorées du tout. Voici donc le workaroud que j'ai effectué et l'explication de pourquoi cela a fonctionné pour moi.

Si vous avez eu la chance d'explorer un peu les événements de glissement, juste un peu, en créant une classe "MiWebView", en écrasant la méthode "onTouchEvent" et en imprimant au moins l'heure à laquelle chaque événement de glissement se produit, vous verrez qu'ils sont séparés à temps pour (jusqu'à) 9 ms. C'est un temps très court entre les événements.

Jetez un œil au code source WebView , et voyez simplement la fonction onTouchEvent. Il est tout simplement impossible qu'elle soit gérée par le processeur en moins de 9ms (Continuez à rêver !!!). C'est pourquoi vous voyez constamment le message "Manquez une traînée car nous attendons la réponse de WebCore pour l'atterrissage." message. Le code ne peut tout simplement pas être traité à temps.

Comment le réparer? Tout d'abord, vous ne pouvez pas réécrire le code onTouchEvent pour l'améliorer, c'est tout simplement trop. Mais, vous pouvez "vous moquer" afin de limiter le taux d'événements pour les mouvements de glissement, disons à 40 ms ou 50 ms. (cela dépend du processeur).

Tous les événements tactiles se présentent comme suit: ACTION_DOWN -> ACTION_MOVE ...... ACTION_MOVE -> ACTION_UP. Nous devons donc garder les mouvements DOWN et UP et filtrer le taux de MOVE (ce sont les méchants).

Et voici un moyen de le faire (vous pouvez ajouter plus de types d'événements comme le toucher à 2 doigts, tout ce qui m'intéresse ici est le défilement à un seul doigt).

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;
    }
}

Bien sûr, utilisez cette classe au lieu de WebView et vous verrez la différence lors du défilement.

Il ne s'agit que d'une approche à une solution, mais qui n'est pas encore entièrement mise en œuvre pour tous les cas de retard en raison du toucher de l'écran lors de l'utilisation de WebView. Cependant, c'est la meilleure solution que j'ai trouvée, au moins pour mes besoins spécifiques.

Nate Castro
la source
Je tiens à souligner que le code source de la vue Web que vous avez posté date de 2010
CQM
Cela ne fonctionne pas, cela ne facilite pas le défilement, je ne sens pas la différence.
neevek
J'ai implémenté ce réglage de la limite jusqu'à 80, mais cela ne semble pas améliorer les performances, mais il détecte certains événements de déplacement. Qu'est-ce que cela fait pour vous?
Ragnar
J'ai lu qu'un événement de clic est 6 fois plus lent que le démarrage tactile de l'événement. Pour éviter les retards, vous pouvez utiliser $ ('# button'). On ('touchstart click', function () {action here; return false;});
Codebeat
De plus, n'utilisez pas l'événement de clic dans vos applications html, il ajoute un délai de 300 ms pour répondre à chaque clic, pour déterminer qu'il s'agit d'un clic. Mieux vaut utiliser le touchstart à la place. J'ai créé un gestionnaire de clics qui utilise deux événements et prend le premier événement déclenché. J'utilise 'touchstart click', donc cela fonctionne toujours sans écran tactile.
Codebeat
9

J'ai essayé toutes les propositions pour résoudre le problème de performances de rendu dans mon application phonegap. Mais rien n'a vraiment fonctionné.

Finalement, après une journée entière de recherche, je l'ai fait. J'ai défini dans la balise (pas la balise) de mon AndroidManifest

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

Maintenant, l'application se comporte de la même manière rapide que mon navigateur Web. On dirait que si l'accélération matérielle n'est pas toujours la meilleure fonctionnalité ...

Le problème détaillé que j'ai eu: https://stackoverflow.com/a/24467920/3595386

user3595386
la source
2
La désactivation de l'accélération matérielle a fait horrible pour moi, la vue Web était si lente à défiler
AbdelHady
5

Aucune de ces réponses ne m'a été utile.

Enfin, j'ai trouvé la raison et la solution. La raison en était beaucoup de filtres CSS3 (filtre, -webkit-filter).

Solution

J'ai ajouté la détection de WebView dans le script de page Web afin d'ajouter la classe "lowquality" au corps HTML. BTW. Vous pouvez facilement suivre WebView en définissant l'agent utilisateur dans les paramètres WebView. Ensuite, j'ai créé une nouvelle règle CSS

body.lowquality * { filter: none !important; }
l00k
la source
Gênant quand 5 ans plus tard, il y a très peu de raisons d'utiliser la vue Web malgré les appareils plus rapides, les performances plus compatibles avec les navigateurs mobiles se sont considérablement améliorées et d'autres raisons. Merci de votre attention!
CQM
@CQM J'ai eu le même problème, j'ai trouvé la solution donc je voulais la partager :)
l00k
Je suis juste facétieux, c'est l'une de mes plus anciennes questions, merci encore!
CQM
1
Il est absurde que ce soit un problème en 2016/2017. Aucun des filtres CSS ne devrait être difficile pour un GPU mobile.
Adam Leggett
4

S'il n'y a que quelques composants de votre vue Web qui sont lents ou lents, essayez d'ajouter ceci aux éléments css:

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

C'est le seul speedhack qui a vraiment eu un effet sur ma vue Web. Mais attention à ne pas en abuser! (vous pouvez en savoir plus sur le piratage dans cet article .)

Erex
la source
1
Utilisez will-change: transform.
Adam Leggett
3

Essaye ça:

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

Si vous vous engagez à l' onclickévénement, il peut être lent sur les écrans tactiles.

Pour le rendre plus rapide, j'utilise fastclick , qui utilise les événements tactiles beaucoup plus rapides pour imiter l'événement de clic.

Tzach
la source
fastclick n'est plus en cours de développement ... oui les événements tactiles sont lents et j'en avais juste besoin pour fonctionner et j'ai trouvé avec jquery que le problème de vitesse peut être résolu en utilisant $('#').on('touchstart', function() {...});par opposition à onclick
CrandellWS