Opóźnienie nawigacji to kluczowy wskaźnik wrażeń użytkownika. Aby pomóc deweloperom zmniejszyć to opóźnienie, WebView udostępnia interfejsy API do ładowania spekulacyjnego i optymalizacji połączeń, dzięki czemu aplikacja może pobierać lub renderować treści, zanim użytkownik do nich przejdzie.
WebView obsługuje 3 główne typy spekulacyjnego wczytywania: wstępne nawiązywanie połączenia, wstępne pobieranie i wstępne renderowanie, a także wskazówki QUIC do optymalizacji negocjacji protokołu.
Wdrażając strategię ładowania spekulacyjnego, możesz osiągnąć następujące korzyści:
- Znaczne skrócenie czasu oczekiwania na wczytanie treści internetowych: przenieś czas rozpoczęcia działania sieci na wcześniejszy etap cyklu życia aplikacji i używaj szybszych protokołów, takich jak HTTP/3.
- Wyższy odsetek udanych nawigacji: dzięki wstępnemu przygotowaniu sieci i pamięci podręcznej nawigacje rzadziej kończą się niepowodzeniem z powodu przejściowych problemów z siecią.
- Lepsza postrzegana szybkość reakcji: renderowanie wstępne umożliwia natychmiastowe przejścia, dzięki czemu aplikacja wydaje się znacznie szybsza.
Wybieranie strategii ładowania spekulacyjnego
Główna różnica między tymi strategiami polega na ich zakresie: interfejsy API wskazówek dotyczących wstępnego połączenia i QUIC są oparte na źródle, co oznacza, że wymagają tylko domeny docelowej. Interfejsy API wstępnego pobierania i wstępnego renderowania są oparte na adresach URL, co oznacza, że wymagają dokładnej ścieżki do strony.
Wskazówki dotyczące wstępnego nawiązywania połączenia i QUIC działają na poziomie źródła, więc możesz je wywoływać, zanim dowiesz się, do jakich konkretnych treści lub stron przejdzie użytkownik.
Poniższa tabela porównuje te 3 strategie, aby pomóc Ci wybrać odpowiednią dla Twojego przypadku:
| Funkcja | Preconnect | Pobieranie z wyprzedzeniem | Renderowanie wstępne |
|---|---|---|---|
| Cel główny | Rozgrzej połączenie | Pamięć podręczna tylko HTML (bez JavaScriptu ani CSS) | Wstępne renderowanie całej strony |
| Zakres | Poziom profilu (udostępniany w widokach WebView) | Poziom profilu (udostępniany w widokach WebView) | Poziom WebView (powiązany z konkretnym komponentem WebView) |
| Jetpack WebKit API | androidx.webkit.Profile |
androidx.webkit.Profile |
androidx.webkit.WebViewCompat |
| Podstawowe metody interfejsu API | preconnect(...) |
prefetchUrlAsync(...) |
prerenderUrlAsync(...) |
| Konfiguracja | Nie dotyczy | PrefetchCache.setMaxPrefetches()PrefetchCache.setPrefetchTtlSeconds() |
setMaxPrerenders() |
| Wykorzystanie zasobów | Niska (sieć) | Średnie (sieć, pamięć) | Wysokie (procesor, pamięć, sieć) |
| Kiedy używać | Gdy znane jest docelowe źródło, ale konkretny adres URL nie został jeszcze określony. | Gdy dokładny adres URL jest znany, a nawigacja jest prawdopodobna, z pamięcią podręczną udostępnianą w widokach WebView. | Gdy dokładny adres URL jest znany, a nawigacja w określonym widoku WebView jest bardzo pewna. |
| Zalety | Szybsze konfigurowanie połączenia z dowolnym adresem URL w domenie źródłowej | Szybsze wczytywanie sieci w przypadku dopasowanych adresów URL | Prawdziwie natychmiastowa nawigacja po aktywacji |
Nawiązywanie połączeń ze źródłami w trybie preconnect
Wstępne łączenie przyspiesza przyszłe ładowanie, ponieważ z wyprzedzeniem wykonuje wyszukiwanie DNS i uzgadnianie połączenia TCP/TLS lub QUIC dla określonego źródła.
W przeciwieństwie do pobierania z wyprzedzeniem i wstępnego renderowania, które wymagają dokładnego docelowego adresu URL, wstępne nawiązywanie połączenia jest oparte wyłącznie na pochodzeniu. Dzięki temu możesz wywołać Preconnect, zanim poznasz dokładny adres URL. Wskazówki dotyczące tego, kiedy wywoływać tę funkcję, znajdziesz w sekcji Implementacja.
Ta strategia na poziomie profilu, która wymaga niewielkich zasobów, zmniejsza początkowe opóźnienie w przypadku udostępniania w dowolnym widoku WebView w tym profilu, pod warunkiem że źródło nie zostało jeszcze odwiedzone. Połączenie pozostaje otwarte przez około 30 sekund, co ułatwia kolejne żądania HTTP ze współdzieleniem zasobów z innych domen, nawigacje i zasoby podrzędne, ponieważ eliminuje narzut związany z uzgadnianiem połączenia. Wynik wyszukiwania DNS jest przechowywany w pamięci podręcznej dłużej niż połączenie, więc późniejsze żądania do serwera źródłowego mogą nadal pomijać wyszukiwanie po zamknięciu połączenia.
Implementacja
Aby zainicjować wstępne połączenie, zadzwoń pod numer preconnect(String url) na instancji Profile. Ten interfejs API musi być wywoływany w wątku UI i wymaga obsługi WebViewFeature.PRECONNECT.
Interfejs API działa na źródle, ale dla wygody można podać pełny adres URL (np. https://www.example.com/index.html). Jest to automatycznie traktowane jako wywołanie źródła (np. https://www.example.com). Z tym interfejsem API można połączyć wiele źródeł, wywołując go wielokrotnie.
Kotlin
// Must be called on the @UiThread
if (WebViewFeature.isFeatureSupported(WebViewFeature.PRECONNECT)) {
profile.preconnect("https://www.example.com/index.html")
// This initiates a connection to the origin https://www.example.com
}
Java
// Must be called on the @UiThread
if (WebViewFeature.isFeatureSupported(WebViewFeature.PRECONNECT)) {
profile.preconnect("https://www.example.com/index.html");
// This initiates a connection to the origin https://www.example.com
}
Wskazywanie obsługi protokołu QUIC za pomocą wskazówek QUIC
HTTP/3 (który działa w protokole transportowym QUIC) zapewnia znacznie mniejsze opóźnienia niż HTTP/2, w tym uzgadnianie połączenia 0-RTT, większą odporność połączenia i eliminację blokowania na początku kolejki w przypadku utraty pakietów.
Domyślnie WebView próbuje nawiązać połączenie QUIC tylko wtedy, gdy ma informację, że pochodzenie obsługuje QUIC, np. z nagłówka Alt-Svc lub rekordu DNS HTTPS z poprzedniej interakcji. Bez tej wiedzy WebView używa protokołu HTTP/2 lub HTTP/1.1 do nawiązania połączenia początkowego.
Wywołanie addQuicHints wstępnie wypełnia informacje o obsłudze protokołu, co umożliwia
WebView natychmiastowe połączenie przy użyciu QUIC podczas pierwszego połączenia z określonymi
źródłami.
Połączenie w trybie preconnect z użyciem wskazówek QUIC
Zarówno wskazówki dotyczące wstępnego nawiązywania połączenia, jak i QUIC to optymalizacje na poziomie źródła w przypadku Profile, ale pełnią różne, uzupełniające się role:
preconnect: aktywnie otwiera i utrzymuje połączenie sieciowe (wyszukiwanie DNS i uzgadnianie połączenia TCP/TLS lub QUIC) przez około 30 sekund. Ponieważ utrzymuje otwarte aktywne połączenia sieciowe, zużywa zasoby urządzenia i sieci, dlatego należy go używać tylko w przypadku docelowych źródeł o wysokim prawdopodobieństwie.addQuicHints: Nie powoduje natychmiastowego ruchu w sieci. Aktualizuje właściwości serwera w pamięciProfilestosu sieciowego, aby rejestrować obsługę protokołu. Ponieważ ma on znikome obciążenie, możesz bezpiecznie skonfigurować wskazówki QUIC podczas uruchamiania aplikacji dla wszystkich znanych źródeł obsługujących HTTP/3.
Aby uzyskać optymalną skuteczność, zadzwoń pod numer addQuicHints przed zadzwonieniem pod numer preconnect,prefetchUrlAsync lub loadUrl. Dzięki temu wszystkie kolejne połączenia wstępne lub żądania stron będą od początku negocjować protokół HTTP/3.
Implementacja
Aby skonfigurować wskazówki QUIC, wywołaj addQuicHints(Set<String> urls) na instancji Profile. Ten interfejs API musisz wywołać w wątku UI i sprawdzić, czy komponent WebView obsługuje funkcję WebViewFeature.ADD_QUIC_HINTS_V1.
Podobnie jak preconnect, addQuicHints działa na podstawie źródeł, ale można podać pełne adresy URL (np. https://www.example.com/index.html), które są automatycznie normalizowane do źródła (https://www.example.com).
Ta metoda jest addytywna: wywołanie jej kilka razy powoduje scalenie podanych domen w Profile.
Kotlin
// Must be called on the @UiThread
@OptIn(Profile.ExperimentalAddQuicHints::class)
if (WebViewFeature.isFeatureSupported(WebViewFeature.ADD_QUIC_HINTS_V1)) {
val quicOrigins = setOf(
"https://www.example.com",
"https://api.example.com"
)
profile.addQuicHints(quicOrigins)
// WebView now prioritizes HTTP/3 over QUIC for connections to these origins
}
Java
// Must be called on the @UiThread
// Requires @Profile.ExperimentalAddQuicHints annotation or suppression
if (WebViewFeature.isFeatureSupported(WebViewFeature.ADD_QUIC_HINTS_V1)) {
Set<String> quicOrigins = new HashSet<>(Arrays.asList(
"https://www.example.com",
"https://api.example.com"
));
profile.addQuicHints(quicOrigins);
// WebView now prioritizes HTTP/3 over QUIC for connections to these origins
}
Typowa konfiguracja: PrefetchParameters i PrerenderParameters
Zarówno w przypadku wstępnego pobierania, jak i wstępnego renderowania do dostosowywania żądania używa się PrefetchParameters lub PrerenderParameters. Te klasy umożliwiają podawanie dodatkowych nagłówków i wskazówek dotyczących dopasowywania adresów URL, np. konfiguracji No-Vary-Search.
Kotlin
// Isolated configuration specifically for Cache-Level Prefetching
val prefetchParams = PrefetchParameters.Builder()
.addAdditionalHeader("X-Custom-Client", "Android-App-V2")
.setExpectedNoVarySearchHeader(
NoVarySearchHeader.varyExcept(true, listOf("session_id", "click_ref"))
)
.build()
Java
PrefetchParameters prefetchParams = new PrefetchParameters.Builder()
.addAdditionalHeader("X-Custom-Header", "value")
/**
* Hint to ignore specific query parameters during cache matching.
* This allows the cache to match even if the tracking_id differs.
*/
.setExpectedNoVarySearchHeader(
NoVarySearchHeader.varyExcept(true, Arrays.asList("tracking_id"))
)
/**
* Determines if Client Hints are sent.
* NOTE: This is ignored for Prerendering API requests, which default to
* the WebView's WebSettings.getJavaScriptEnabled() value.
*/
.setJavaScriptEnabled(true)
.build();
Pobieranie treści z wyprzedzeniem
Pobieranie z wyprzedzeniem pobiera główny zasób HTML adresu URL i przechowuje go w pamięci podręcznej sieci profilu. W komponencie WebView obiekt Profile pełni funkcję kontenera danych przeglądarki, w tym plików cookie, pamięci podręcznej HTTP i procesów roboczych usługi. Prefetch to operacja na poziomie profilu, więc każdy WebView powiązany z tym profilem może korzystać z odpowiedzi w pamięci podręcznej.
Implementacja
Aby zainicjować wstępne pobieranie, wywołaj metodę prefetchUrlAsync() w instancji Profile. Ta operacja obsługuje tylko schemat HTTPS.
Kotlin
profile.prefetchUrlAsync(
url,
prefetchParams,
cancellationSignal,
executor,
object : WebViewOutcomeReceiver<PrefetchResult, PrefetchException> {
override fun onResult(result: PrefetchResult) {
if (result.wasDuplicate()) {
// URL and No-Vary-Search permutations already exist in the cache layer
} else {
// The HTML payload has been successfully secured in the HTTP cache
}
}
override fun onError(error: PrefetchException) {
when (error) {
is PrefetchNetworkException -> {
// Isolates network layer or server-side HTTP anomalies
val code = error.httpStatusCode
// Facilitates rapid diagnosis of 4xx or 5xx server responses
}
else -> {
// Catches generalized execution failures and system constraints
}
}
}
}
)
Java
profile.prefetchUrlAsync(
url,
prefetchParams,
cancellationSignal,
executor,
new WebViewOutcomeReceiver<PrefetchResult, PrefetchException>() {
@Override
public void onResult(PrefetchResult result) {
if (result.wasDuplicate()) {
// URL and No-Vary-Search permutations already exist in the cache layer
} else {
// The HTML payload has been successfully secured in the HTTP cache
}
}
@Override
public void onError(PrefetchException error) {
if (error instanceof PrefetchNetworkException) {
// Isolates network layer or server-side HTTP anomalies
int code = ((PrefetchNetworkException) error).httpStatusCode;
// Facilitates rapid diagnosis of 4xx or 5xx server responses
} else {
// Catches generalized execution failures and system constraints
}
}
}
);
Cykl życia przechwytywania
Prośba o wstępne pobranie WebView zmienia moment i sposób wywoływania shouldInterceptRequest()
wywołania zwrotnego. Ma to bezpośredni wpływ na to, czy wstępnie pobrane treści zostaną użyte, dlatego ważne jest, aby poznać 2-etapowy cykl życia:
1. Faza spekulacyjna (żądanie wstępnego pobrania)
Gdy wywoływana jest funkcja prefetchUrlAsync(), WebView pobiera w tle główny zasób HTML. shouldInterceptRequest() jest całkowicie pomijany w przypadku tego żądania w tle. Żadna niestandardowa logika, tokeny autoryzacji ani wstrzykiwanie nagłówków, które są zwykle obsługiwane w interceptorze, nie są stosowane do wstępnie pobranego zasobu HTML.
2. Faza nawigacji (aktywacja użytkownika)
Gdy aplikacja wyraźnie przechodzi do adresu URL (np. za pomocą WebViewCompat.navigate lub loadUrl) albo użytkownik kliknie pasujący link, komponent WebView sprawdza, czy może użyć wstępnie pobranej pamięci podręcznej:
Ocena głównego kodu HTML: w tym momencie WebView wywoła
shouldInterceptRequest()dla głównego kodu HTML. Aby strona została wyświetlona z pamięci podręcznej pobierania wstępnego, przechwytujący musi zwrócić wartośćnull. Jeśli zwrócisz niestandardowyWebResourceResponse, WebView uwzględni Twój przechwytujący i całkowicie pominie pamięć podręczną wstępnego pobierania.Ocena zasobów podrzędnych: po tym, jak wstępnie pobrany kod HTML zostanie dopuszczony do użycia,
shouldInterceptRequest()tagi są zwykle wywoływane w przypadku wszystkich kolejnych zasobów podrzędnych (takich jak obrazy, skrypty i arkusze CSS) wymaganych do zakończenia renderowania strony.
Kluczowe zachowania
Sposób, w jaki WebView inicjuje żądania wstępnego pobierania i nimi zarządza, zależy od tych cech operacyjnych i sprawdzania kryteriów:
- Bezpieczeństwo wątków: żądania można inicjować z dowolnego wątku.
- Kwalifikacja: przed rozpoczęciem pobierania WebView sprawdza, czy żądanie jest bezpieczne i odpowiednie w kontekście, wykonując te czynności:
- Istniejące pliki cookie: aby chronić prywatność użytkowników i zapobiegać efektom ubocznym podobnym do CSRF, WebView może pominąć wstępne pobieranie, jeśli żądanie wymaga określonych uwierzytelnionych plików cookie, które mogą spowodować zmianę stanu na serwerze.
- Obecność skryptu service worker: jeśli skrypt service worker kontroluje już zakres adresu URL, komponent WebView może przekazać obsługę pobierania do skryptu service worker zamiast inicjować standardowe pobieranie z wyprzedzeniem z sieci.
- Dostępność serwera proxy: komponent WebView sprawdza, czy bieżąca ścieżka sieciowa (w tym skonfigurowane serwery proxy) jest stabilna, aby uniknąć niepowodzeń spekulacyjnych żądań w przypadku złożonych konfiguracji sieci.
- Jeśli wstępne pobieranie nie rozpocznie się (nawet z prawidłowymi parametrami), często dzieje się tak, ponieważ komponent WebView uznał, że żądanie w tle może zakłócić bieżącą sesję użytkownika lub stan bezpieczeństwa.
- Anulowanie: użyj parametru
CancellationSignal, aby zakończyć trwające żądanie i zapobiec jego zapisaniu w pamięci podręcznej.
Renderowanie wstępne stron
Renderowanie wstępne tworzy ukryte „treści z internetu”, aby w pełni renderować stronę w tle, w tym wykonywać skrypty i pobierać zasoby podrzędne. Wstępne renderowanie korzysta z tej samej infrastruktury co wstępne pobieranie. Jeśli aplikacja zainicjuje wstępne renderowanie, komponent WebView najpierw pobierze wstępnie odpowiedź, aby obsłużyć nawigację wstępnego renderowania, unikając zbędnej aktywności sieciowej.
Implementacja
Wstępne renderowanie to operacja na poziomie instancji WebView. Wywołaj funkcję prerenderUrlAsync()
za pomocą funkcji WebViewCompat z wątku UI.
Kotlin
WebViewCompat.prerenderUrlAsync(
webView,
url,
cancellationSignal,
executor,
params,
object : PrerenderOperationCallback {
override fun onPrerenderActivated() {
// Called when the user navigates to the URL and the hidden page is swapped in
}
override fun onError(exception: Throwable) {
// exception is an instance of PrerenderException
// Handle prerender failure (for example, memory pressure or disallowed JavaScript APIs)
}
}
)
Java
WebViewCompat.prerenderUrlAsync(webView, url, cancellationSignal, executor, params, new PrerenderOperationCallback() {
@Override
public void onPrerenderActivated() {
// Called when the user navigates to the URL and the hidden page is swapped in.
}
@Override
public void onError(@NonNull Throwable exception) {
// Handle prerender failure (for example, resource constraints or disallowed APIs).
}
});
Zarówno pobieranie z wyprzedzeniem, jak i wstępne renderowanie są w pełni asynchroniczne. prefetchUrlAsync() można wywołać z dowolnego wątku, a prerenderUrlAsync() musi zostać zainicjowany z wątku UI.
Ograniczenia techniczne
Aby zachować równowagę między natychmiastową nawigacją a stanem systemu, WebView wymusza te ograniczenia w czasie działania:
- Obciążenie pamięci: WebView anuluje wstępnie wyrenderowane adresy URL, jeśli urządzenie ma mało pamięci RAM.
- Niedozwolone interfejsy API: wszelkie próby uzyskania przez JavaScript dostępu do niektórych interfejsów API (np. odtwarzania dźwięku, alertów) w kontekście tła spowodują natychmiastowe zakończenie wstępnego renderowania.
- Limit instancji: liczba aktywnych wstępnie renderowanych adresów URL dozwolonych w każdym widoku WebView jest ograniczona.
Dopasowywanie adresów URL i dyrektywa No-Vary-Search (NVS)
WebView wymaga niezawodnego algorytmu dopasowywania, aby mieć pewność, że wstępnie wczytany zasób będzie wyświetlany tylko w przypadku zamierzonej nawigacji.
Dopasowanie ścisłe a dopasowanie NVS
Domyślnie wstępne pobieranie i wstępne renderowanie wymagają dokładnego dopasowania adresu URL. Jeśli adres URL, do którego nastąpiło przekierowanie, jest identyczny z wstępnie załadowanym adresem URL, jest on natychmiast obsługiwany z pamięci podręcznej. Jeśli parametry zapytania się różnią, WebView stosuje te reguły No-Vary-Search (NVS):
- Wskazówka: deweloperzy podają
setExpectedNoVarySearchHeader()wskazówkę podczas inicjowania. Jeśli adres URL, do którego nastąpiło przejście, pasuje do adresu URL żądania bez parametrów podpowiedzi, WebView na krótko blokuje działanie, aby poczekać na rzeczywiste nagłówki serwera. - Nagłówek serwera: nagłówek odpowiedzi NVS z serwera jest ostatecznym źródłem informacji. Jeśli serwer potwierdzi, że różnice w zapytaniu należy zignorować, dopasowanie zostanie wyświetlone z pamięci podręcznej. W przeciwnym razie WebView przechodzi do zimnego wczytywania sieci.
Dyrektywa No-Vary-Search (NVS) jest przeznaczona do zaawansowanego użytku i większość deweloperów może jej nie potrzebować, ponieważ przekazują ten sam adres URL zarówno do pobierania z wyprzedzeniem, jak i do nawigacji (WebViewCompat.navigate lub loadUrl). Te wskazówki są potrzebne tylko wtedy, gdy występują różnice w parametrach zapytania między adresem URL pobierania z wyprzedzeniem a adresem URL nawigacji.
Konfiguracja globalna
Dostosuj działanie ładowania spekulacyjnego na poziomie profilu, konfigurując PrefetchCachelimity i maksymalną liczbę wstępnych renderowań. Możesz też przywrócić niestandardowe limity wstępnego pobierania do ustawień domyślnych:
Kotlin
// Configure prefetch cache limits
profile.prefetchCache.setMaxPrefetches(10)
profile.prefetchCache.setPrefetchTtlSeconds(60)
// Reset to system defaults when needed
profile.prefetchCache.clearMaxPrefetches()
// Configure maximum active prerenders
profile.setMaxPrerenders(2)
Java
// Configure prefetch cache limits
PrefetchCache prefetchCache = profile.getPrefetchCache();
prefetchCache.setMaxPrefetches(10);
prefetchCache.setPrefetchTtlSeconds(60);
// Reset to system defaults when needed
prefetchCache.clearMaxPrefetches();
// Configure maximum active prerenders
profile.setMaxPrerenders(2);
Obsługa błędów i wyjątków
Operacje spekulacyjne używają symbolu OutcomeReceiverCompat lub PrerenderOperationCallback do raportowania wyników.
Wyjątki podstawowe
Gdy operacja ładowania spekulacyjnego zakończy się niepowodzeniem, moduł obsługi błędów zgłosi jeden z tych głównych typów wyjątków, aby ułatwić Ci diagnozowanie konkretnych scenariuszy niepowodzenia:
PrefetchException: klasa bazowa dla wszystkich błędów asynchronicznego pobierania z wyprzedzeniem.PrefetchNetworkException: wskazuje błąd na poziomie sieci lub serwera. Może zawierać polehttpStatusCode(np. 404 lub 503), które pomaga diagnozować problemy po stronie serwera.PrerenderException: klasa nadrzędna wszystkich błędów związanych z wstępnym renderowaniem, np. błędów spowodowanych brakiem pamięci lub użyciem w tle niedozwolonych interfejsów API (takich jak odtwarzanie dźwięku).
Strategie optymalizacji
Aby zmaksymalizować korzyści wynikające z ładowania spekulacyjnego, a jednocześnie oszczędzać zasoby systemu, postępuj zgodnie z tymi zaleceniami:
- Wcześniejsze inicjowanie: wstępne pobieranie danych należy rozpocząć podczas uruchamiania aplikacji lub gdy tylko pojawi się prawdopodobieństwo, że użytkownik przejdzie do miejsca docelowego nawigacji.
- Łączenie wskazówek QUIC z wstępnym rozgrzewaniem połączenia: wywołaj
addQuicHints()przed rozpoczęciem nawigacjipreconnect(),prefetchUrlAsync()lub standardowej, aby mieć pewność, że WebView podejmie próbę nawiązania połączeń za pomocą protokołu HTTP/3. - Strategia zintegrowana: jeśli wstępnie renderujesz adres URL, który jest już w pamięci podręcznej wstępnego pobierania, nawigacja wstępnego renderowania jest obsługiwana z tej pamięci podręcznej, co pozwala uniknąć zbędnych żądań sieciowych.
- Monitoruj limity: wstępne renderowanie jest zasobożerne. W przypadku kilku prawdopodobnych kandydatów preferuj wstępne pobieranie, a wstępne renderowanie rezerwuj dla najbardziej prawdopodobnej nawigacji.
- Obsługa schematu: upewnij się, że wszystkie adresy URL korzystają z obowiązkowego schematu HTTPS. Nieprawidłowe schematy lub puste dane wejściowe wywołują synchroniczną funkcję
IllegalArgumentException.
Dodatkowe materiały
Więcej informacji o debugowaniu aplikacji internetowych, optymalizowaniu wydajności uruchamiania WebView i obsłudze zakończenia procesu renderowania znajdziesz w tych materiałach:
- Ulepszona nawigacja na stronie za pomocą metody
WebViewCompat.navigate - Debugowanie aplikacji internetowych
- Optymalizacja uruchamiania komponentu WebView
- Obsługa zakończenia procesu renderowania WebView