Подтвердить что ты не робот

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
4b9b3361

Ответ 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();
        }
    }