Widok internetowy w Androidzie wolno

174

Moje android webviewssą powolne. Dotyczy to wszystkiego, od telefonów po 3.0+tablety z więcej niż odpowiednimi specyfikacjami

Wiem, że wyświetlenia w sieci powinny być „ograniczone”, ale widzę aplikacje internetowe wykonane z przerwą między telefonami, które muszą wykorzystywać różne rodzaje CSS3i JQuerymagię, działają dobrze i szybko

więc czegoś mi brakuje, czy jest coś, myWebview.SPEEDHACK(1)czego mogę użyć do przyspieszenia?

Ponadto czasami zawartość mojego widoku po prostu się nie ładuje, zamiast powoli się ładować, po prostu się nie ładuje. Zasób, z którym testuję, jest przechowywany lokalnie, bez błędów.

CQM
źródło
3
Wygląda na to, że musisz opublikować jakiś kod.
Jasoneer,
1
możliwy duplikat wydajności Android WebView
Ken White
1
@KenWhite poza tym, że to pytanie ma więcej odpowiedzi, to pytanie ma lepsze i bardziej wyczerpujące odpowiedzi, to pytanie ma dwa razy więcej poglądów, oba pytania mają ponad dwa lata, wersja Androida oba te pytania są przestarzałe ... co dokładnie czy unikniesz zgłaszania tego?
CQM
@CQM: To pytanie zostało automatycznie oflagowane przez system z powodu zduplikowanej odpowiedzi George'a Maysa poniżej. Jeśli jego odpowiedź można powtórzyć dosłownie jako odpowiedź na wiele postów, jeden z nich jest duplikatem drugiego. Połączone pytanie zostało opublikowane (i udzielono na nie odpowiedzi) jako pierwsze na podstawie daty publikacji. Duplikat to duplikat, a pierwszy post był oryginałem (i odpowiedzi były również wcześniejsze). Nie mam nic z oflagowania tego (i przede wszystkim tego nie zrobiłem).
Ken White
1
Ponadto nie używaj zdarzenia kliknięcia w swoich aplikacjach, dodaje ono 300 ms opóźnienia, aby odpowiedzieć na każde kliknięcie, aby określić, że jest to kliknięcie. Zamiast tego lepiej użyj touchstartu. Zrobiłem clickhandler, który używa dwóch zdarzeń i przyjmuje pierwsze wywołane zdarzenie. Używam „touchstart click”, więc działa też bez ekranu dotykowego.
Codebeat

Odpowiedzi:

132

Zależy to od ładowanej aplikacji internetowej. Wypróbuj niektóre z poniższych podejść:

Ustaw wyższy priorytet renderowania (wycofany z API 18+):

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

Włącz / wyłącz akcelerację sprzętową:

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

Wyłącz pamięć podręczną (jeśli masz problemy z zawartością):

webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
peceps
źródło
46
Rozumiem, dlaczego ustawienie wysokiego priorytetu renderowania przyspieszyłoby to. ale po co wyłączać pamięć podręczną?
Dimas Kotvan
39
Metoda setRederPriority jest przestarzała, patrz developer.android.com/reference/android/webkit/WebSettings.html
Victor Ionescu
6
Prawidłowy link do setRenderPriority jest tutaj
Christopher Perry
2
Gdzie umieścić ten kod w mojej aplikacji? Proszę o pomoc - mam ten sam problem w
widoku
6
dlaczego wyłączasz pamięć podręczną?
Hassy 31
52

Dodanie tego android:hardwareAccelerated="true"do manifestu było jedyną rzeczą, która znacznie poprawiła dla mnie wydajność

Więcej informacji tutaj: http://developer.android.com/guide/topics/manifest/application-element.html#hwaccel

Nadawca
źródło
1
Dotyczy to tylko API v11 / Android 3.xi nowszych
Ludwo
6
Uważaj, istnieje otwarty błąd związany ze sprzętowym przyspieszeniem WebViews, jak stwierdzono w pytaniu stackoverflow.com/q/17059899/225341
Victor Ionescu
1
Zauważyłem, że wyłączenie akceleracji sprzętowej w rzeczywistości przyspiesza moją aplikację. Ponieważ android:hardwareAccelerated="true"animacje CSS 3D miały duże opóźnienia przed rozpoczęciem, przewijanie DIV w innych przewijalnych DIV nie działało, a aplikacja była bardziej niestabilna.
Ernests Karlsons
1
domyślną wartością jest „true”, jeśli ustawiłeś minSdkVersion lub targetSdkVersion na „14” lub wyższą;
Vihaan Verma
37

Dla nas rozwiązanie było odwrotne. Wyłączyliśmy akcelerację sprzętową tylko w WebView (a nie w całej aplikacji w manifeście) za pomocą tego kodu:

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

Animacje CSS3 są teraz płynniejsze. Używamy Androida 4.0.

Więcej informacji tutaj: https://code.google.com/p/android/issues/detail?id=17352

Włącz
źródło
4
Niestety, uniemożliwia to również działanie komponentu wideo html5 = /
Ja Aprck
Nie zauważyłem. Użyliśmy widoku wideo do odtwarzania filmów: na szczęście potrzebowaliśmy tylko wideo na pełnym ekranie. Aby obejść ten problem, widok sieciowy może być przezroczysty, a widok wideo odtwarzany w tle, chociaż wiem, że to nie to samo.
Ena
1
Jest inny problem z tą poprawką. Podczas dotykania widoku internetowego grafika jest nieco zniekształcona. Na przykład, jeśli masz obraz z kółkiem, zauważysz na nim małe kwadraty (piksele) zamiast gładkiej linii. Wiem, że z Androidem 4.3 poprawka jest bezużyteczna, nie ma problemów z wydajnością.
Ena
Przepraszam, trochę nowy dla Androida. Czy można to wkleić bezpośrednio w manifeście Androida, ponieważ plik manifestu jest XML. Czy też ma to zostać sprawdzone w kodzie źródłowym podczas ładowania widoku internetowego. Przepraszam za pytanie noob.
xMythicx
1
Po dodaniu pojawia się ten błądWebView not displayed because it is too large to fit into a software layer (or drawing cache), needs 11534400 bytes, only 8294400 available
developer1011
14

Myślę, że najlepiej działa:

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 ma silnik Chromium dla WebView. Myślę, że działa lepiej z akceleracją sprzętową.

Tedi
źródło
1
To zadziałało w przypadku WebViews z kiepskimi animacjami i przewijaniem
cal
Czy to ja, czy twoje „inne” działa tak samo jak „jeśli”?
Codebeat
Erwinus jeden jest dla type_SOFTWARE, a drugi Hardware
user2582318
9

Miałem ten sam problem i musiałem to rozwiązać. Wypróbowałem te rozwiązania, ale ostatecznie wydajność, przynajmniej przy przewijaniu, wcale się nie poprawiła. A więc tutaj obejście, które wykonałem, i wyjaśnienie, dlaczego zadziałało.

Jeśli miałeś okazję zbadać zdarzenia przeciągania, tylko trochę, tworząc klasę "MiWebView", nadpisując metodę "onTouchEvent" i przynajmniej wypisując czas, w którym występuje każde zdarzenie przeciągania, zobaczysz, że są one oddzielone w czasie do (do) 9 ms dalej. To bardzo krótki czas pomiędzy wydarzeniami.

Spójrz na kod źródłowy WebView i po prostu zobacz funkcję onTouchEvent. Po prostu niemożliwe jest, aby procesor mógł to obsłużyć w czasie krótszym niż 9 ms (Śnij dalej !!!). Dlatego ciągle widzisz komunikat „Przegap się, ponieważ czekamy na odpowiedź WebCore na lądowanie”. wiadomość. Kod po prostu nie może być obsłużony na czas.

Jak to naprawić? Po pierwsze, nie możesz ponownie napisać kodu onTouchEvent, aby go ulepszyć, to po prostu za dużo. Możesz jednak „kpić z tego”, aby ograniczyć częstotliwość zdarzeń w przypadku ruchów przeciągania, powiedzmy do 40 ms lub 50 ms. (zależy to od procesora).

Wszystkie zdarzenia dotykowe wyglądają tak: ACTION_DOWN -> ACTION_MOVE ...... ACTION_MOVE -> ACTION_UP. Musimy więc zachować ruchy W DÓŁ i W GÓRĘ oraz filtrować tempo RUCHU (to są źli ludzie).

A oto sposób na zrobienie tego (możesz dodać więcej typów zdarzeń, takich jak dotknięcie dwoma palcami, wszystko, co mnie interesuje, to przewijanie jednym palcem).

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

Oczywiście użyj tej klasy zamiast WebView, a zobaczysz różnicę podczas przewijania.

To tylko podejście do rozwiązania, ale wciąż nie w pełni zaimplementowane we wszystkich przypadkach opóźnienia z powodu dotykania ekranu podczas korzystania z WebView. Jest to jednak najlepsze rozwiązanie, jakie znalazłem, przynajmniej dla moich konkretnych potrzeb.

Nate Castro
źródło
Chciałbym zaznaczyć, że opublikowany przez Ciebie kod źródłowy Webview pochodzi z roku 2010
CQM
To nie działa, nie wygładza przewijania, nie czuję różnicy.
neevek
Zaimplementowałem to ustawienie limitu do 80, ale w rzeczywistości nie wydaje się, aby poprawić wydajność, ale łapie niektóre zdarzenia związane z ruchem. Co to dla Ciebie robi?
Ragnar
Przeczytałem, że kliknięcie jest 6 razy wolniejsze niż touchstart. Aby uniknąć opóźnień, możesz użyć $ ('# button'). On ('touchstart click', function () {akcja tutaj; return false;});
Codebeat
Ponadto nie używaj zdarzenia kliknięcia w aplikacjach HTML, dodaje 300 ms opóźnienia, aby odpowiedzieć na każde kliknięcie, aby określić, że jest to kliknięcie. Zamiast tego lepiej użyj touchstartu. Zrobiłem clickhandler, który używa dwóch zdarzeń i przyjmuje pierwsze wywołane zdarzenie. Używam „touchstart click”, więc nadal działa bez ekranu dotykowego.
Codebeat
9

Wypróbowałem wszystkie propozycje rozwiązania problemu z wydajnością renderowania w mojej aplikacji phonegap. Ale tak naprawdę nic nie działało.

Wreszcie, po całym dniu poszukiwań, udało mi się. Ustawiłem w tagu (nie w tagu) mojego pliku AndroidManifest

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

Teraz aplikacja zachowuje się tak samo szybko, jak moja przeglądarka internetowa. Wygląda na to, że akceleracja sprzętowa nie zawsze jest najlepszą funkcją ...

Szczegółowy problem, który miałem: https://stackoverflow.com/a/24467920/3595386

user3595386
źródło
2
Wyłączenie akceleracji sprzętowej było dla mnie okropne, widok strony przewijał się tak wolno
AbdelHady
5

Żadna z tych odpowiedzi nie była dla mnie pomocna.

Wreszcie znalazłem powód i rozwiązanie. Powodem było wiele filtrów CSS3 (filter, -webkit-filter).

Rozwiązanie

Dodałem wykrywanie WebView w skrypcie strony internetowej w celu dodania klasy „niskiej jakości” do treści HTML. BTW. Możesz łatwo śledzić WebView, ustawiając klienta użytkownika w ustawieniach WebView. Następnie stworzyłem nową regułę CSS

body.lowquality * { filter: none !important; }
l00k
źródło
Niezręczne, gdy 5 lat później istnieje bardzo niewiele powodów do korzystania z widoku internetowego, mimo że urządzenia są szybsze, znacznie poprawiła się wydajność zgodna z przeglądarkami mobilnymi i inne powody. Ale dzięki za przyjrzenie się temu!
CQM
@CQM Miałem ten sam problem, znalazłem rozwiązanie, więc chciałem się nim podzielić :)
l00k
Po prostu żartuję, to jedno z moich najstarszych pytań, jeszcze raz dziękuję!
CQM
1
To absurd, że jest to problem w 2016/2017. Żaden z filtrów CSS nie powinien stanowić wyzwania dla żadnego mobilnego GPU.
Adam Leggett
4

Jeśli tylko kilka elementów Twojego widoku internetowego jest powolne lub opóźnione, spróbuj dodać to do elementów css:

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

To był jedyny speedhack, który naprawdę wpłynął na mój widok. Ale uważaj, aby go nie nadużywać! (możesz przeczytać więcej o włamaniu w tym artykule ).

Erex
źródło
1
Użyj will-change: transform.
Adam Leggett,
3

Spróbuj tego:

mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
George Maisuradze
źródło
3

Jeśli wiążesz się z onclickwydarzeniem, może ono być powolne na ekranach dotykowych.

Aby przyspieszyć, używam fastclick , który wykorzystuje znacznie szybsze zdarzenia dotykowe, aby naśladować zdarzenie kliknięcia.

Tzach
źródło
fastclick nie jest już rozwijany ... tak, zdarzenia dotykowe są powolne i po prostu potrzebowałem go do działania i odkryłem, że w jquery problem z szybkością można obejść, używając $('#').on('touchstart', function() {...});w przeciwieństwie do onclick
CrandellWS