0

There is CustomWebViewClient with override function onPageFinished. What is the shortest way to notify MainViewModel about the function triggered? I mean some event.

I suppose that can use StateFlow, something like this:

class MainViewModel : ViewModel() { 
    init {
        val client = CustomWebViewClient()
        viewModelScope.launch {
            client.onPageFinished.collect {
                // ...
            }
        }
    }
}

class CustomWebViewClient() : WebViewClient() {

    private val _onPageFinished = MutableStateFlow("")
    val onPageFinished = _onPageFinished.asStateFlow()

    override fun onPageFinished(view: WebView, url: String) {
        _onPageFinished.update { "" }
    }
}

But in this case need to transfer unnecessary empty string and will be occurs first call before onPageFinished called because MutableStateFlow has value. So appear required add some enum or class in order to do filter with when keyword.

Maybe is there more shortest way to do that?

Viewed
  • 1,159
  • 3
  • 16
  • 43

2 Answers2

1

You can add lambda parameter into CustomWebViewClient constructor that will get called once page is finished.

class MainViewModel : ViewModel() { 
    init {
        val client = CustomWebViewClient({handle the event})
    }
}

class CustomWebViewClient(onPageFinished: () -> Unit) : WebViewClient() {
    override fun onPageFinished(view: WebView, url: String) {
        onPageFinished()
    }
}

Please note that referencing anything from android.* package in a ViewModel is most often a big no-go.

Mieszko Koźma
  • 460
  • 4
  • 10
  • Can you explain more about referencing? At this time `View` get `Client` from `ViewModel`: `binding.webView.webViewClient = viewModel.client` – Viewed Jul 07 '22 at 14:47
  • I don't know what you're creating, but what stops you from using WebViewClient in a view layer? – Mieszko Koźma Jul 07 '22 at 14:50
  • I base on [this](https://stackoverflow.com/a/72833748/5894542) answer. The three paragraph from below explain why `View` get referring to `Client` from `ViewModel`. – Viewed Jul 07 '22 at 15:07
1

If you want to use the MutablStateFlow approach, another option is to also override onPageStarted as well and do something like

class CustomWebViewClient(): WebViewClient() {
    private val _onPageFinished = MutableStateFlow(false)
    val onPageFinished = _onPageFinished.asStateFlow()
    override fun onPageStarted(
        view: WebView?,
        url: String?,
        favicon: Bitmap?,
    ) {
        _onPageFinished.update { false }
    }

    override fun onPageFinished(view: WebView?, url: String?) {
        _onPageFinished.update { true }
    }
}

class MainViewModel : ViewModel() {
    init {
        val client = CustomWebViewClient()
        viewModelScope.launch {
            client.onPageFinished.collect {
                if (it) {
                    // Do stuff when page is loaded
                } else {
                    // Do stuff when page starts loading
                }
            }
        }
    }
}

Though ultimately using flows for this is kinda overkill and using the lambda approach suggested by Mieszko Koźma is probably more straight forward.

undermark5
  • 775
  • 6
  • 17