Visualização da web do Android lenta

174

Os meus android webviewssão lentos. Isso 3.0+inclui tudo, desde telefones a tablets com especificações mais que adequadas

Eu sei que webviews é suposto ser "limitado" mas vejo Web Apps feito com gap de telefone que devem estar usando todos os tipos de CSS3e JQueryfeitiçaria, eles correm muito bem e rápida

então estou perdendo alguma coisa, existe algum tipo de coisa myWebview.SPEEDHACK(1)que eu possa usar para acelerar as coisas?

além disso, às vezes o conteúdo da minha visualização na web simplesmente não carrega, em vez de carregar lentamente, ele simplesmente não carrega. O ativo com o qual estou testando é armazenado localmente, sem erros.

CQM
fonte
3
Parece que você precisa postar algum código.
Jasoneer 14/09/11
1
possível duplicata do desempenho
Ken White
1
@KenWhite, exceto que esta pergunta tem mais respostas, esta pergunta tem respostas melhores e mais abrangentes, esta pergunta tem o dobro de visualizações, ambas as perguntas têm mais de dois anos, a versão do android, ambas as perguntas aplicadas são obsoletas ... o que exatamente você sai de sinalizar isso?
CQM 28/02
@CQM: Esta pergunta foi sinalizada automaticamente pelo sistema devido à resposta duplicada de George Mays abaixo. Se a resposta dele puder ser repetida literalmente como resposta a várias postagens, uma delas é uma duplicata da outra. A pergunta vinculada foi postada (e respondida) primeiro com base na data da postagem. Uma duplicata é uma duplicata, e o primeiro post foi o original (e as respostas também foram anteriores). Não recebo nada por sinalizar isso (e não o fiz em primeiro lugar).
Ken White
1
Além disso, não use o evento click nos seus aplicativos, ele adiciona um atraso de 300 ms para responder a cada clique e determinar se é um clique. Melhor usar o touchstart. Eu criei um manipulador de cliques que usa dois eventos e leva o primeiro evento acionado. Eu uso o 'touchstart click', por isso também funciona sem uma tela de toque.
Codebeat

Respostas:

132

Depende do aplicativo da web que está sendo carregado. Experimente algumas das abordagens abaixo:

Defina uma prioridade de renderização mais alta (descontinuada da API 18+):

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

Ativar / desativar a aceleração 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);
}

Desative o cache (se você tiver problemas com o seu conteúdo):

webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
peceps
fonte
46
Entendo por que definir a prioridade de renderização como alta a tornaria mais rápida. mas por que desligar o cache?
Dimas Kotvan
39
O método setRederPriority foi descontinuado, consulte developer.android.com/reference/android/webkit/WebSettings.html
Victor Ionescu
6
O link correto para setRenderPriority está aqui
Christopher Perry
2
Onde coloco esse código no meu aplicativo? Por favor, ajuda - Eu tenho o mesmo problema em missão WebView crítica
Levchik
6
por que você desliga o cache?
Hassy31
52

Acrescentar isso android:hardwareAccelerated="true"no manifesto foi a única coisa que melhorou significativamente o desempenho para mim

Mais informações aqui: http://developer.android.com/guide/topics/manifest/application-element.html#hwaccel

Remetente
fonte
1
Isso é apenas para API v11 / Android 3.xe superior
Ludwo 27/05
6
Tome cuidado, há um bug aberto hardware relacionado acelerado WebViews, como indicado na pergunta stackoverflow.com/q/17059899/225341
Victor Ionescu
1
Percebi que desativar a aceleração de hardware torna meu aplicativo mais rápido. Com android:hardwareAccelerated="true"as animações em CSS 3D, houve um longo atraso antes de começar, a rolagem de DIVs dentro de outras DIVs roláveis ​​não funcionou e o aplicativo ficou mais instável.
Ernests Karlsons
1
o valor padrão é "true" se você definiu minSdkVersion ou targetSdkVersion como "14" ou superior;
precisa saber é o seguinte
37

A solução para nós foi o oposto. Desabilitamos a aceleração de hardware apenas no WebView (em vez de no aplicativo inteiro no manifesto) usando este código:

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

As animações CSS3 são mais suaves agora. Estamos usando o Android 4.0.

Mais informações aqui: https://code.google.com/p/android/issues/detail?id=17352

Ena
fonte
4
Infelizmente, isso também impede que o componente de vídeo HTML5 para trabalho = /
Jack
Não percebeu. Usamos uma visualização de vídeo para reproduzir vídeos: felizmente, precisávamos de um vídeo em tela cheia. Como solução alternativa, é possível ter a visualização na web transparente e uma exibição de vídeo em segundo plano, embora eu saiba que não é a mesma coisa.
Ena
1
Há outro problema com essa correção. Ao tocar na visualização na web, o gráfico fica um pouco distorcido. Por exemplo, se você tiver uma imagem com um círculo, notará pequenos quadrados (pixels) em vez da linha suave. Posso dizer que, com a correção do Android 4.3, é inútil, não há problemas de desempenho.
Ena
Desculpe um pouco novo para o Android. Isso é passável diretamente no manifesto do Android, pois o arquivo do manifesto é XML. Ou isso deve ser validado no código-fonte ao carregar a visualização na web. Desculpe pela pergunta noob.
XMythicx
1
Depois de adicionar, obtendo este erroWebView not displayed because it is too large to fit into a software layer (or drawing cache), needs 11534400 bytes, only 8294400 available
developer1011
14

Eu acho que o seguinte funciona melhor:

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

O Android 19 tem mecanismo Chromium para WebView. Eu acho que funciona melhor com aceleração de hardware.

Tedi
fonte
1
Isso funcionou para mim em WebViews com animações pobres e rolagem
cal
Sou eu ou o seu 'mais' faz o mesmo que o seu 'se'?
Codebeat
O Erwinus um é para type_SOFTWARE e o outro Hardware
user2582318
9

Eu estava tendo esse mesmo problema e tive que resolvê-lo. Tentei essas soluções, mas no final o desempenho, pelo menos para a rolagem, não melhorou nada. Então aqui está a solução alternativa que eu realizei e a explicação de por que funcionou para mim.

Se você teve a chance de explorar os eventos de arrasto, criando um pouco da classe "MiWebView", substituindo o método "onTouchEvent" e imprimindo pelo menos a hora em que cada evento de arrasto ocorre, você verá que eles estão separados a tempo de (até) 9ms de distância. Esse é um período muito curto entre os eventos.

Veja o código-fonte do WebView e veja a função onTouchEvent. É simplesmente impossível que ele seja manuseado pelo processador em menos de 9ms (continue sonhando !!!). É por isso que você vê constantemente a mensagem "Não se preocupe, pois estamos aguardando a resposta do WebCore para o toque". mensagem. O código simplesmente não pode ser tratado a tempo.

Como corrigi-lo? Primeiro, você não pode reescrever o código onTouchEvent para melhorá-lo, é demais. Mas você pode "zombar" para limitar a taxa de eventos para movimentos de arrasto, digamos 40ms ou 50ms. (isso depende do processador).

Todos os eventos de toque são assim: ACTION_DOWN -> ACTION_MOVE ...... ACTION_MOVE -> ACTION_UP. Portanto, precisamos manter os movimentos DOWN e UP e filtrar a taxa de MOVE (esses são os bandidos).

E aqui está uma maneira de fazer isso (você pode adicionar mais tipos de eventos, como o toque de 2 dedos, tudo o que me interessa aqui é a rolagem com um 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;
    }
}

É claro que use esta classe em vez do WebView e você verá a diferença ao rolar.

Esta é apenas uma abordagem para uma solução, mas ainda não totalmente implementada para todos os casos de atraso devido ao toque na tela ao usar o WebView. No entanto, é a melhor solução que encontrei, pelo menos para minhas necessidades específicas.

Nate Castro
fonte
Gostaria de salientar que o código-fonte webview você postou é a partir de 2010
CQM
Isso não funciona, não suaviza a rolagem, não consigo sentir a diferença.
neevek
Eu implementei essa configuração no limite de até 80, mas na verdade não parece melhorar o desempenho, mas captura alguns eventos de movimentação. O que ele faz para você?
Ragnar
Você já leu que um evento de clique é 6 vezes mais lento que o touchstart do evento. Para evitar atrasos, você pode usar $ ('# button'). On ('touchstart click', function () {action here; return false;});
Codebeat 28/03
Além disso, não use o evento click em seus aplicativos html; ele adiciona um atraso de 300ms para responder a cada clique e determinar se é um clique. Melhor usar o touchstart. Eu criei um manipulador de cliques que usa dois eventos e leva o primeiro evento acionado. Eu uso o 'touchstart click', para que ele ainda funcione sem uma tela de toque.
Codebeat
9

Tentei todas as propostas para corrigir o problema de desempenho de renderização no meu aplicativo phonegap. Mas nada realmente funcionou.

Finalmente, depois de um dia inteiro de busca, consegui. Defino na tag (não na tag) do meu AndroidManifest

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

Agora, o aplicativo se comporta da mesma maneira rápida que o meu navegador da web. Parece que, se a aceleração do hardware nem sempre é o melhor recurso ...

O problema detalhado que tive: https://stackoverflow.com/a/24467920/3595386

user3595386
fonte
2
Desactivar a aceleração de hardware foi horrível para mim, o webview era tão lento na rolagem
AbdelHady
5

Nenhuma dessas respostas não foi útil para mim.

Finalmente encontrei razão e solução. O motivo foi muitos filtros CSS3 (filtro, -webkit-filter).

Solução

Eu adicionei a detecção do WebView no script da página da web para adicionar a classe "baixa qualidade" ao corpo do HTML. Entre. Você pode acompanhar facilmente o WebView definindo user-agent nas configurações do WebView. Então eu criei uma nova regra CSS

body.lowquality * { filter: none !important; }
l00k
fonte
Inábil quando cinco anos depois, existem muito poucas razões para usar a visualização na web, apesar de os dispositivos serem mais rápidos, o desempenho mais compatível com o navegador móvel melhorou bastante e outras razões. Obrigado por investigar!
CQM 21/10
@CQM Eu tive o mesmo problema, eu encontrei uma solução, então eu queria compartilhá-lo :)
l00k
Só estou sendo ridículo, esta é uma das minhas perguntas mais antigas, obrigado novamente!
CQM 21/10
1
É absurdo que esse seja um problema em 2016/2017. Nenhum dos filtros CSS deve ser desafiador para qualquer GPU móvel.
23917 Adam Adgetgett
4

Se houver apenas alguns componentes do seu webview lentos ou atrasados, tente adicionar isso aos elementos css:

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

Este foi o único speedhack que realmente afetou minha visualização na web. Mas tome cuidado para não usá-lo demais! (você pode ler mais sobre o hack neste artigo .)

Erex
fonte
1
Use will-change: transform.
23917 Adam Adgetgett
3

Tente o seguinte:

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

Se você está vinculando ao onclickevento, pode ser lento nas telas sensíveis ao toque.

Para torná-lo mais rápido, eu uso o fastclick , que usa os eventos de toque muito mais rápidos para imitar o evento de clique.

Tzach
fonte
FastClick não está mais sendo desenvolvido ... sim os eventos de toque são lentos e eu só precisava para o trabalho e encontrou com jQuery a questão da velocidade pode ser contornado usando $('#').on('touchstart', function() {...});em oposição a onclick
CrandellWS