WebView не удается отобразить до тех пор, пока не коснется Android 4.2.2
Я разрабатываю браузер с открытым исходным кодом под названием Lightning Browser, и у меня возникли проблемы с самым последним обновлением для Android (4.2.2).
WebViews не сможет полностью отобразиться до тех пор, пока не коснется вид. Это происходит только в последней версии Android. В 4.2.1 WebView визуализируется полностью. Я использую свой Nexus 7 для разработки, и сразу после того, как я получил обновление 4.2.2, браузер остановил рендеринг. Другие пользователи испытали это также, и это было подтверждено несколько раз, чтобы ТОЛЬКО на 4.2.2. Это происходит с ориентацией на уровень API 16 и 17, но я видел, что браузер WebKit ориентирован на уровень API 9 без этой проблемы.
Я попытался исправить это, используя решение проблемы, которую я нашел здесь в Qaru (Android WebView отображает пустой/белый, просмотр не обновляется при изменениях css или изменениях HTML, анимация изменчивая). ОДНАКО, установка WebView RenderPriority на высокий уровень не решает его... единственный способ заставить его визуализировать, не будучи затронутым, состоял в том, чтобы поместить команду invalidate() в метод OnDraw() WebView. Это заставляет WebView повторно рисовать непрерывно. Это работает (вроде), анимация плавная, страница загружается очень быстро, но это приводит к тому, что производительность WebView падает иначе.
Я тоже видел этот вопрос (очень похожий на мой), но для него нет хорошего ответа. Android WebView не удается полностью отобразить контент до взаимодействия с пользователем
По мере снижения производительности я подразумеваю ввод. Недостатки ввода текста, и сам WebView не может справиться с тем, что происходит, как и раньше. Бенчмаркинг браузера с вызовом метода invalidate() снижает производительность бенчмаркинга примерно на 8%. Я знаю, что в тестах есть не все, но он говорит мне, что непрерывный рисунок напрягает систему и заставляет систему игнорировать другие задачи.
В заключение...
WebView в Android 4.2.2 не будет отображаться до тех пор, пока не коснется. Единственный способ, который я знаю, чтобы исправить это, - вызвать invalidate() в методе onDraw() WebView. Это плохо для производительности, и я ищу другой способ исправить это.
Магический код (в настоящее время я использую)...
class MyWebView extends WebView
{
@Override
onDraw(Canvas canvas)
{
invalidate();
super.OnDraw(canvas);
}
}
удалить
invalidate();
и он не отображается до тех пор, пока не коснется.
Есть ли у кого-нибудь предложения о том, как сделать рендеринг WebView (кроме того, что я сделал)? Кстати, это мой первый вопрос, который я задал здесь на Stack, так что простите меня, если я не был ясен или если я сделал что-то не так.
EDIT:
Я нашел этот вопрос здесь об аналогичной проблеме, и это было решено, проблема в том, что я не понимаю, что означает ответ. Если бы кто-нибудь мог просветить меня, это могло бы помочь.
Я получаю эту ошибку в logcat
E/chromium(1243): external/chromium/net/disk_cache/backend_impl.cc:2022: [0705/172030:ERROR:backend_impl.cc(2022)] Corrupt Index file
Ответы
Ответ 1
Итак, я, наконец, нашел проблему, из-за которой WebView не отображался. Я запускаю и останавливаю анимацию вытачиваемого внутри WebViewClient моего WebView. Этот drawable - это просто кнопка обновления, которая вращается при загрузке страницы... простое право?
Хорошо в режиме без полноэкранного режима браузера вращающиеся чертежи и WebView являются дочерними родителями одного и того же родителя, тогда как в полноэкранном режиме вытягиваемый становится дочерним элементом WebView. Как бы то ни было, при запуске анимации, когда страница загружается и останавливается, когда она выполняется (в полноэкранном режиме), приложение решает, что вращающийся чертеж - это то, что требует всей мощности рисования, и WebView никогда не рисует. Когда в полноэкранном режиме, а drawable становится дочерним элементом WebView, WebView имеет более высокий приоритет рендеринга, чем рисоваемый, и он отлично рисует.
Мораль этой истории... WebViews, как будто это самый высокий приоритетный вид. Если другие взгляды имеют больший приоритет, они не будут правильно рисоваться.
Я не эксперт в анимации, поэтому мне нужно переосмыслить, как я анимирую выделение сейчас, чтобы не прерывать WebView.
Надеюсь, это имело смысл. Спасибо за чтение.
Ответ 2
Отключить аппаратное ускорение в вашем манифесте:
Android: hardwareAccelerated = "ложь"
Ответ 3
см. последний ответ от @Olivier на Android WebView отображает пустой/белый, просмотр не обновляется при изменениях css или изменениях в HTML, анимация изменчив, он запускает пару задержек, недействительных на WebView OnTouchEvent, а не постоянно на onDraw... В моем случае это сработало, потому что (большинство) моих проблем были после того, как пользователь коснулся веб-представления, и я изменил некоторые CSS в ответ. Конечно, это вообще не применяется в случае автоматического/тайм-аута css
В моем случае это также помогло экспортировать функцию JavaScript из Java, чтобы вручную запускать invalidate с задержкой, поэтому, если в JavaScript вы более или менее знаете, где может произойти бедствие, вы можете вручную запустить его, что-то вроде этого внутреннего класса внутри ваш WebView:
public class MyWebView extends WebView {
private class InvalidateExtension {
private Handler handler=new Handler(); // you might already have a handler
private Runnable mInvalidater=new Runnable() {
@Override
public void run() {
MyWebView.this.invalidate();
}
}
public void trigger(int delay) {
handler.postDelayed(mInvalidater, delay);
handler.postDelayed(mInvalidater, 2*delay); // just in case
handler.postDelayed(mInvalidater, 4*delay); // just in case just in case :)
}
}
/** Call this function on this view init, BEFORE loading a page so it is available to JS */
private void call_me_on_init_to_enable_hack() {
addJavascriptInterface(new InvalidateExtension(), "Invalidater");
}
}
Итак, из JavaScript вы можете:
Invalidater.trigger(100);
И играйте с миллисекундным значением....
Надеюсь, это поможет кому-то!
Ответ 4
При повороте телефона возникает проблема с масштабом масштабирования, и это вызовет эту проблему, детали или целую страницу не будут нарисованы. Чтобы решить эту переопределение onScaleChanged в вашей реализации WebViewClient и аннулировать представление. Это должно заставить перерисовать, когда это необходимо.
@Override
public void onScaleChanged(WebView view, float oldScale, float newScale) {
if (view != null) {
view.invalidate();
}
}