Skip to content
Source

WebView and Compose

In our application, quite a lot of features are opened simply as WebView with a bunch of different settings, hooks, overriding URL loading logic, many parameters in cookies, and so on, not to mention all sorts of browser tricks like permissions and file pickers. And for several months now we've been approaching the idea of taking all this logic from the fragment and stuffing it into bare Compose to calmly embed it in the Decompose hierarchy. And for several weeks now I've been trying to digest it all in the background. Thoughts.

The task essentially divides into two. The first is a generic WebView wrapper in AndroidView. That is, literally a "replacement" for the classic WebView for Compose. The state of the industry is such that there's no official wrapper from Google. Well, that is, how there isn't, there's a Deprecated implementation in Accompanist, which Google themselves suggest forking because they gave up maintaining it. And it's not that it's bad, at first glance it even solves trivial cases like loading a URL without extra settings, but you really need to get used to it. Like much from Google, it somehow very ugly sticks out Android dependencies like clients, bitmaps, and so on. It's too straightforwardly implemented. So first of all you want to write a wrapper on a wrapper, yeah.

If you dig deeper, then any obvious feature like pull-to-refresh is done in such a setup with pain and suffering. Seriously, there on StackOverflow the only working answer seems to involve using the view SwipeRefreshLayout inside the same AndroidView with WebView. But this is not even a problem of this particular solution, this is in principle a problem of AndroidView in Compose. Thank God, no one has come up with this feature for us yet.

The second part of the task, actually, given the first is much more difficult. You need to write such a Decompose component (well, or ViewModel) that will describe the "screen" feature with this WebView and hold all its logic. And here begins an adventure of 20 minutes. On one hand, it's convenient for you to work with it directly from Compose since all these states-navigators-clients are encapsulated there, on the other hand you want to keep the state outside Compose, for clients dependencies exist outside Compose, and so on. And here you understand for the second time that most of the code from Accompanist didn't imply such a thing at all and you catch yourself starting to drive everything imperatively through their navigator, abandoning declarative options.

Continuing observation, maybe in a week everything will change for me.