Slide 1

Slide 1 text

WebView DroidKaigi.onCompletion { 20 23 @Online } (@mr_mkeeda)

Slide 2

Slide 2 text

About me Twitter: @mr_mkeeda Github: @mkeeda Android Engineer at Cybozu, Inc kintone 2

Slide 3

Slide 3 text

WebView WebView 3

Slide 4

Slide 4 text

WebView URL/HTML 4

Slide 5

Slide 5 text

UI 5 WebView Fragment loadUrl( URL) reload() WebViewClient onPageStarted() onPageFinished() shouldOverrideUrlLoading()

Slide 6

Slide 6 text

WebView Fragment loadUrl( URL) reload() WebViewClient onPageStarted() onPageFinished() shouldOverrideUrlLoading() 6 Fragment 500 WebView

Slide 7

Slide 7 text

7 https://developer.android.com/topic/architecture

Slide 8

Slide 8 text

UI 8 UI Elements UI State = UI

Slide 9

Slide 9 text

: Web 9 UI Elements UI State = UI WebView URL Web =

Slide 10

Slide 10 text

= URL 10 UI elements WebView UI state URL A = UI Web A UI elements WebView UI state URL B = UI Web B

Slide 11

Slide 11 text

WebView 11 UI elements WebView State holder ViewModel UI state URL 3. URL 2 . URL (UI event) 1. URL 4. URL

Slide 12

Slide 12 text

12 UI elements WebView State holder ViewModel UI state URL UI state UI state

Slide 13

Slide 13 text

WebView android.widget UI state Callback UI state WebView 13 UI state URL UI elements WebView

Slide 14

Slide 14 text

URL 14 WebViewClient shouldOverrideUrlLoading() UI elements WebView UI state URL A State holder ViewModel ❌ return true loadUrl() UI state URL B WebViewClient# 
 shouldOverrideUrlLoading() true URL URL UI state URL B

Slide 15

Slide 15 text

15 class WebViewModel : ViewModel() { private val _currentUrl = MutableStateFlow(Uri.parse("https://www.google.com")) val url: StateFlow = _currentUrl.asStateFlow() fun onPageLoad(newUrl: Uri) { _currentUrl.update { currentUrl -> // ೚ҙͷϩδοΫ // … newUrl } } } // Composeableؔ਺ val url by viewModel.url.collectAsStateWithLifecycle() WebScreen( url = url, onUrlChanged = { newUrl -> viewModel.onPageLoad(newUrl) } )

Slide 16

Slide 16 text

16 @Composable fun WebScreen( url: Uri, onUrlChanged: (Uri) -> Unit ) { AndroidView( factory = { context -> WebView(context).apply { webViewClient = MyWebViewClient(onUrlChanged) } }, update = { webView -> webView.loadUrl(url.toString()) } ) } class MyWebViewClient( private val onUrlChanged: (Uri) -> Unit ) : WebViewClientCompat() { override fun shouldOverrideUrlLoading( view: WebView, request: WebResourceRequest ): Boolean { onUrlChanged(request.url) return true } }

Slide 17

Slide 17 text

WebView UI state 
 https://github.com/mkeeda/webview-sandbox WebView 17 Do not call WebView#loadUrl(String) with the request's URL and then return true. This unnecessarily cancels the current load and starts a new load with the same URL. https://developer.android.com/reference/android/webkit/WebViewClient