WebViewCompat.navigate,
WebView.loadUrl का बेहतर विकल्प है. यह वेब पेज लोड करने,
इतिहास मैनेज करने, और WebView में नेविगेशन लाइफ़साइकल को ट्रैक करने की सुविधा देता है.
पहले, loadUrl का इस्तेमाल करके पेज नेविगेशन शुरू करने में ये समस्याएं आती थीं:
- इतिहास की एंट्री को बदला नहीं जा सकता: मौजूदा इतिहास की एंट्री को बदला नहीं जा सकता था. इसलिए, बैक स्टैक में एंट्री जोड़े बिना किसी नए पेज पर नेविगेट नहीं किया जा सकता था.
- अलग-अलग कॉलबैक:
WebViewClientमें, किसी खासloadUrlकॉल को उसके बाद होने वाले कॉलबैक इवेंट से सीधे तौर पर कोरिलेट करने का कोई तरीका नहीं था. - अतिरिक्त हेडर सेव नहीं किए जाते थे:
loadUrlको पास किए गए कस्टम हेडर,WebViewकी स्थिति के हिस्से के तौर पर सेव नहीं किए जाते थे. इसलिए, स्थिति को वापस लाने पर वे गायब हो जाते थे.
WebViewCompat.navigate API, इन समस्याओं को हल करता है. इसके लिए, इसमें ये सुविधाएं जोड़ी गई हैं:
- नेविगेशन इतिहास की एंट्री को बदलना: इससे,
WebViewके इतिहास स्टैक में मौजूद मौजूदा पेज को बदला जा सकता है. - कोरिलेटेड कॉलबैक ट्रैकिंग: यह
Navigationऑब्जेक्ट दिखाता है. यह नेविगेशन लाइफ़साइकल के सभी चरणों में, यूनीक आइडेंटिफ़ायर के तौर पर काम करता है. - सेव की गई स्थिति के हेडर के लिए सहायता: अतिरिक्त हेडर,
WebViewके सेव किए गए स्थिति बंडल में सेव किए जाते हैं. इससे, स्थिति को वापस लाने पर उनका फिर से इस्तेमाल किया जा सकता है.
मुख्य सुविधाएं और सीमाएं
WebViewCompat.navigate को अपनाने से पहले, इन नियमों और पाबंदियों के बारे में जान लें:
थ्रेड की सुरक्षा: आपको यूज़र इंटरफ़ेस (यूआई) (मुख्य) थ्रेड पर
WebViewCompat.navigateको लागू करना होगा.रद्द करना और प्राथमिकता: फ़्लाइट में मौजूद नेविगेशन को साफ़ तौर पर रद्द नहीं किया जा सकता. हालांकि, एक ही
WebViewपर नयाnavigateकॉल शुरू करने से, चालू नेविगेशन रद्द हो जाता है.यूआरआई स्कीम के लिए सहायता: स्टैंडर्ड (जैसे,
https:औरhttp:) और कस्टम यूआरआई स्कीम के लिए सहायता उपलब्ध है.javascript:स्कीम के लिए सहायता उपलब्ध नहीं है.यूआरएल के साइज़ की सीमा: यूआरएल स्ट्रिंग की ज़्यादा से ज़्यादा लंबाई 2 एमबी हो सकती है.
सुविधा की उपलब्धता की जांच: अलग-अलग WebView APK वर्शन के साथ काम करने की सुविधा बनाए रखने के लिए, API को लागू करने से पहले हमेशा
WebViewFeature.isFeatureSupportedका इस्तेमाल करके, सुविधा की उपलब्धता की जांच करें.
नेविगेशन शुरू करना और लाइफ़साइकल को ट्रैक करना
नेविगेशन को कॉन्फ़िगर करने और उसके लाइफ़साइकल को ट्रैक करने के लिए, यह तरीका अपनाएं:
WebViewसेटअप के दौरान,WebViewCompat.addNavigationListenerका इस्तेमाल करकेNavigationListenerलागू करने की सुविधा रजिस्टर करें. इससे, आपको स्ट्रक्चर्ड लाइफ़साइकल कॉलबैक मिलेंगे. मेमोरी लीक और डुप्लीकेट कॉलबैक को रोकने के लिए, हर नेविगेशन कॉल पर रजिस्टर करने के बजाय, लिसनर को एक बार रजिस्टर करें.NavigationParametersइंस्टेंस बनाने के लिए,NavigationParameters.Builderका इस्तेमाल करें. इससे, इतिहास को बदलने या कस्टम एचटीटीपी हेडर जैसे वैकल्पिक व्यवहार तय किए जा सकते हैं.WebViewCompat.navigateको कॉल करें. इसके लिए, अपनाWebViewइंस्टेंस, डेस्टिनेशन यूआरएल, और पैरामीटर पास करें.
WebViewCompat.navigate एक Navigation ऑब्जेक्ट दिखाता है. यह अनुरोध की यूनीक
पहचान करता है. आपके NavigationListener कॉलबैक में, इस ऑब्जेक्ट की तुलना आने वाले Navigation पैरामीटर से करें. इससे, उस खास नेविगेशन को ट्रैक किया जा सकेगा.
लागू करने का उदाहरण
यहां दिए गए उदाहरण में बताया गया है कि नेविगेशन पैरामीटर को कैसे कॉन्फ़िगर किया जाता है, WebViewCompat.navigate को कैसे लागू किया जाता है, और नेविगेशन लाइफ़साइकल इवेंट को कैसे सुना जाता है:
Kotlin
class WebNavigationManager(private val webView: WebView) {
// Track the navigation instance returned by the API
private var currentNavigation: Navigation? = null
init {
// 1. Define listener to observe navigation lifecycle events
val listener = object : NavigationListener {
override fun onNavigationStarted(navigation: Navigation) {
if (navigation == currentNavigation) {
// Navigation started
}
}
override fun onNavigationRedirected(navigation: Navigation) {
if (navigation == currentNavigation) {
// Navigation encountered a redirect
}
}
override fun onNavigationCompleted(navigation: Navigation) {
if (navigation == currentNavigation) {
if (navigation.didCommit()) {
// Navigation committed successfully
} else if (navigation.didCommitErrorPage()) {
// Navigation committed an error page
val statusCode = navigation.statusCode
val error = navigation.webResourceError
}
}
}
override fun onFirstContentfulPaintMillis(page: Page, durationMillis: Long) {
// Match page with current navigation
if (page == currentNavigation?.page) {
// Page rendering started (First Contentful Paint achieved)
}
}
}
// 2. Register listener on the main thread
WebViewCompat.addNavigationListener(webView, listener)
}
@UiThread
fun navigateToPage(url: String) {
// Check feature availability
if (!WebViewFeature.isFeatureSupported(WebViewFeature.WEBVIEW_NAVIGATE_EXPERIMENTAL_V1)) {
// Fall back to standard loadUrl if navigate API is unavailable
webView.loadUrl(url)
return
}
// 3. Configure navigation parameters
val params = NavigationParameters.Builder()
.setShouldReplaceCurrentEntry(true)
.addAdditionalHeaders(
mapOf("X-Test-Navigate-Header" to "TestValue")
)
.build()
// 4. Initiate navigation on the UI thread
currentNavigation = WebViewCompat.navigate(webView, url, params)
}
}
Java
public class WebNavigationManager {
private Navigation mCurrentNavigation;
private final WebView mWebView;
public WebNavigationManager(@NonNull WebView webView) {
mWebView = webView;
setupListener();
}
private void setupListener() {
// 1. Define listener to observe navigation lifecycle events
NavigationListener listener = new NavigationListener() {
@Override
public void onNavigationStarted(@NonNull Navigation navigation) {
if (navigation.equals(mCurrentNavigation)) {
// Navigation started
}
}
@Override
public void onNavigationRedirected(@NonNull Navigation navigation) {
if (navigation.equals(mCurrentNavigation)) {
// Navigation encountered a redirect
}
}
@Override
public void onNavigationCompleted(@NonNull Navigation navigation) {
if (navigation.equals(mCurrentNavigation)) {
if (navigation.didCommit()) {
// Navigation committed successfully
} else if (navigation.didCommitErrorPage()) {
// Navigation committed an error page
int statusCode = navigation.getStatusCode();
WebResourceErrorCompat error = navigation.getWebResourceError();
}
}
}
@Override
public void onFirstContentfulPaintMillis(@NonNull Page page, long durationMillis) {
if (mCurrentNavigation != null && page.equals(mCurrentNavigation.getPage())) {
// Page rendering started (First Contentful Paint achieved)
}
}
};
// 2. Register listener on the main thread
WebViewCompat.addNavigationListener(mWebView, listener);
}
@UiThread
public void navigateToPage(@NonNull String url) {
// Check feature availability
if (!WebViewFeature.isFeatureSupported(WebViewFeature.WEBVIEW_NAVIGATE_EXPERIMENTAL_V1)) {
// Fall back to standard loadUrl if navigate API is unavailable
mWebView.loadUrl(url);
return;
}
// 3. Configure navigation parameters
NavigationParameters params = new NavigationParameters.Builder()
.setShouldReplaceCurrentEntry(true)
.addAdditionalHeaders(Collections.singletonMap(
"X-Test-Navigate-Header", "TestValue"
))
.build();
// 4. Initiate navigation on the UI thread
mCurrentNavigation = WebViewCompat.navigate(mWebView, url, params);
}
}
विफल होने के तरीके और गड़बड़ी ठीक करना
WebViewCompat.navigate API, कॉन्फ़िगरेशन की गड़बड़ियों और रनटाइम नेविगेशन की समस्याओं को ठीक करने के लिए अलग-अलग तरीके उपलब्ध कराता है:
अमान्य आर्ग्युमेंट से जुड़ी गड़बड़ियां
अमान्य आर्ग्युमेंट पास करने पर, IllegalArgumentException सिंक में ट्रिगर होता है.
इसकी आम वजहें यहां दी गई हैं:
- ज़रूरी नॉन-नल पैरामीटर (
webView,url, याparams) के लिएnullपास करना. - ऐसी यूआरएल स्कीम देना जो काम नहीं करती, जैसे कि
javascript:. - गलत तरीके से फ़ॉर्मैट किए गए एचटीटीपी हेडर की पासकोड या वैल्यू पास करना. ये RFC 2616 की खास जानकारी के मुताबिक नहीं होती हैं.
नेविगेशन प्रोसेस की गड़बड़ियां
अगर नेटवर्क का अनुरोध या पेज लोड होने के दौरान कोई गड़बड़ी होती है (जैसे, एचटीटीपी 404 स्टेटस कोड, डीएनएस रिज़ॉल्यूशन में गड़बड़ी या एसएसएल की गड़बड़ी), तब भी WebViewCompat.navigate मान्य Navigation ऑब्जेक्ट दिखाता है.
नेविगेशन पूरा होने पर, गड़बड़ी की पहचान करने के लिए, अपने onNavigationCompleted कॉलबैक में Navigation
इंस्टेंस पर ये तरीके देखें:
getStatusCode: एचटीटीपी रिस्पॉन्स स्टेटस कोड दिखाता है. जैसे,404या500.getWebResourceError:WebResourceErrorCompatऑब्जेक्ट दिखाता है. इसमें नेटवर्क की गड़बड़ियों के बारे में जानकारी होती है. जैसे, कनेक्शन टाइम आउट या होस्ट लुकअप में गड़बड़ी.didCommitErrorPage: इससे पता चलता है किWebViewने उपयोगकर्ता को गड़बड़ी वाला पेज दिखाया है या नहीं.didCommit: इससे पता चलता है कि नेविगेशन, बिना रद्द किए, टारगेट पेज पर सफलतापूर्वक पूरा हुआ है या नहीं.
सेव किए गए स्थिति बंडल को मैनेज करना
जब NavigationParameters के साथ अतिरिक्त हेडर पास किए जाते हैं, तो WebView इन हेडर को अपने सेव किए गए स्थिति बंडल में सेव करता है. इससे, स्थिति को वापस लाने पर उनका फिर से इस्तेमाल किया जा सकता है. हालांकि, हेडर के बड़े कलेक्शन की वजह से, सेव किए गए स्थिति Bundle का साइज़ काफ़ी बढ़ सकता है.
अगर आपको Android की स्थिति सेव करने के दौरान TransactionTooLargeException
से बचने के लिए, बंडल के साइज़ को सीमित करना है, तो WebViewCompat.saveStateका इस्तेमाल करें. इस तरीके से, बाइट में बंडल के साइज़ की ज़्यादा से ज़्यादा सीमा सेट की जा सकती है. साथ ही, आगे के इतिहास के आइटम को शामिल न करने का विकल्प भी चुना जा सकता है:
Kotlin
// Save state with a maximum bundle size limit (for example, 64 KB)
val maxSizeBytes = 64 * 1024
val includeForwardState = false
val outState = Bundle()
WebViewCompat.saveState(webView, outState, maxSizeBytes, includeForwardState)
Java
// Save state with a maximum bundle size limit (for example, 64 KB)
int maxSizeBytes = 64 * 1024;
boolean includeForwardState = false;
Bundle outState = new Bundle();
WebViewCompat.saveState(webView, outState, maxSizeBytes, includeForwardState);
इससे बनने वाला बंडल, स्टैंडर्ड
WebView.restoreState तरीके के साथ काम करता है.
माइग्रेट करने और लागू करने से जुड़े सुझाव
WebView में नेविगेट करते समय, बेहतर परफ़ॉर्मेंस और स्थिरता बनाए रखने के लिए, इन सुझावों को अपनाएं:
loadUrlसेnavigateपर माइग्रेट करें: सभी पुरानेWebView.loadUrlकॉल कोWebViewCompat.navigateपर माइग्रेट करें. इससे, इतिहास को एक जैसा मैनेज किया जा सकेगा. साथ ही, यह पक्का किया जा सकेगा कि हेडर हमेशा सेव की गई स्थिति के हिस्से के तौर पर सेव किए जाएं.सुविधा की उपलब्धता की हमेशा पुष्टि करें: API को लागू करने से पहले, रनटाइम सहायता की पुष्टि करने के लिए
WebViewFeature.isFeatureSupportedका इस्तेमाल करें. इससे, WebView के पुराने वर्शन से सुरक्षा मिलेगी.नेविगेशन इंस्टेंस को कोरिलेट करें: एक साथ होने वाले नेविगेशन में अंतर करने या एक से ज़्यादा
WebViewइंस्टेंस मैनेज करते समय कॉलबैक को फ़िल्टर करने के लिए, दिखाए गएNavigationऑब्जेक्ट का इस्तेमाल करें.शुरू करने के दौरान, लिसनर को एक बार रजिस्टर करें: क्योंकि
WebViewCompat.addNavigationListenerमौजूदा लिसनर को बदलने के बजाय, एक लिसनर जोड़ता है. इसलिए,WebViewसेटअप के दौरान, अपनेNavigationListenerको एक बार रजिस्टर करें. इससे, मेमोरी लीक और बाद के नेविगेशन में डुप्लीकेट कॉलबैक को रोका जा सकेगा.सेव की गई स्थिति के साइज़ पर नज़र रखें: बड़े हेडर पेलोड पास करते समय,
WebViewCompat.saveStateका इस्तेमाल करें. साथ ही, साइज़ की सीमाएं साफ़ तौर पर तय करें. इससे, ज़्यादा स्थिति डेटा सेव होने से रोका जा सकेगा.
अन्य संसाधन
एम्बेड किए गए वेब की सुविधाओं और परफ़ॉर्मेंस ऑप्टिमाइज़ेशन के बारे में ज़्यादा जानने के लिए, ये गाइड देखें:
- Jetpack Webkit की मदद से, WebView को आसानी से लागू करना
- WebView में अनुमान के हिसाब से यूआरएल लोड होने की सुविधा
- WebView के स्टार्टअप को ऑप्टिमाइज़ करना
- WebView रेंडरर प्रोसेस के बंद होने की समस्या को ठीक करना