Как безопасно включать и выключать масштабирование WebView при необходимости - PullRequest
7 голосов
/ 11 марта 2011

Как уже упоминалось в этом неотвеченном вопросе: WebView выбрасывает Receiver не зарегистрировано: android.widget.ZoomButtonsController

При включении и выключении элементов управления масштабированием WebView при необходимости выдается следующее:

java.lang.IllegalArgumentException: Receiver not registered: android.widget.ZoomButtonsController

Для некоторых пользователей.Я сам не видел этот сбой, но я видел его в журналах, поступающих с устройств в дикой природе.Это не случается очень часто, но это крушение независимо.Есть идеи?

Спасибо

Обновление: Как воспроизвести

Я нашел, как воспроизвести этот сбой: http://code.google.com/p/android/issues/detail?id=15694

Я сообщу, если найду обходной путь.


В соответствии с запросом, полная трассировка стека:

java.lang.IllegalArgumentException: Receiver not registered: android.widget.ZoomButtonsController$1@487a4290
at android.app.ActivityThread$PackageInfo.forgetReceiverDispatcher(ActivityThread.java:793)
at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:913)
at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:331)
at android.widget.ZoomButtonsController.setVisible(ZoomButtonsController.java:404)
at android.widget.ZoomButtonsController$2.handleMessage(ZoomButtonsController.java:178)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)

и другой аналогичный:

java.lang.IllegalArgumentException: View not attached to window manager
at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:391)
at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:236)
at android.view.Window$LocalWindowManager.removeView(Window.java:432)
at android.widget.ZoomButtonsController.setVisible(ZoomButtonsController.java:406)
at android.widget.ZoomButtonsController$2.handleMessage(ZoomButtonsController.java:178)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:5068)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

Ответы [ 9 ]

10 голосов
/ 11 мая 2011

В Xoom я обнаружил, что если кто-то ждет, когда элемент управления масштабированием исчезнет, ​​прежде чем вызывать WebView.destroy (), сбой больше не происходит. Поэтому я переписал WebView.destroy (), чтобы отправить сообщение в обработчик для вызова WebView.destroy () через несколько секунд. Из источника WebView мы видим, что интервал затухания:

// The time that the Zoom Controls are visible before fading away
private static final long ZOOM_CONTROLS_TIMEOUT =
        ViewConfiguration.getZoomControlsTimeout();

Поэтому я использовал ViewConfiguration.getZoomControlsTimeout () + 1000L в качестве задержки перед вызовом метода уничтожения в WebView. Пока не вылетает.

8 голосов
/ 30 июля 2011

Если вы хотите, чтобы масштабирование работало только с вашим веб-представлением, и вы можете жить без кнопок масштабирования, вы можете сделать это для своего веб-просмотра:

webView.getSettings().setBuiltInZoomControls(true); // will give pinch zoom
webView.getSettings().setDisplayZoomControls(false); // but won't display the zoom buttons

добавление

webView.getSettings().setBuiltInZoomControls(true);

в onDestroy / onDestroyView не помогло на 3.x.

7 голосов
/ 06 марта 2012

webView.getSettings () setBuiltInZoomControls (истина).у меня не сработало.

Предложение Дкнеллера сработало, однако:

    long timeout = ViewConfiguration.getZoomControlsTimeout();
    new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
            webview.destroy();
        }
    }, timeout);
5 голосов
/ 26 апреля 2012

Поместите эту строку в Дестрой, у меня работает:

webView.setVisibility(View.GONE);

3 голосов
/ 09 декабря 2015

Это решение отлично работает, вам просто нужно удалить веб-представление из макета, прежде чем уничтожить его:

@Override
    public void onDestroy() {
        if (webView!=null && webView.getParent()!=null){
            ((ViewGroup)webView.getParent()).removeView(webView);
            webView.destroy();
            webView=null;
        }
        super.onDestroy();
    }

Нет обработчиков, нет задержек, я думаю, что это лучшее решение

2 голосов
/ 23 марта 2011

Если вы наткнулись на этот вопрос, не забудьте сначала проверить отчет об ошибке, чтобы узнать, какой статус у Google, но в остальном вот обходной путь, который мне пока подходит:

Добавьте эту строку в ваш метод onDestory ():

webView.getSettings().setBuiltInZoomControls(true);
0 голосов
/ 14 мая 2016

Добавьте это к вашей деятельности:

@Override
  public void finish() {
      ViewGroup view = (ViewGroup) getWindow().getDecorView();
      view.removeAllViews();
      super.finish();
}
0 голосов
/ 20 марта 2011

У меня та же проблема: Существующее приложение взрывается с Android 3.0 XOOM.ZoomButtonsController Leak?

Это происходит, когда возникает исключение, которое происходит до вызова registerReceiver, а затем вы позже пытаетесь отменить регистрацию Receiver без его регистрации.

Вероятно, это ошибка Android 3.0.

0 голосов
/ 19 марта 2011

java.lang.IllegalArgumentException: представление не присоединено к оконному менеджеру. Исключение чаще всего возникает, когда есть диалоговое окно (т. Е. Диалоговое окно хода выполнения), и вы закрываете его, когда действие закрывается. Не могли бы вы сказать, действительно ли в вашей Деятельности есть диалог прогресса, чтобы я мог продолжить анализ? Также опубликуйте фрагмент кода вашей активности, который может помочь нам определить причину сбоя вашего приложения ...

Также вы говорите, что не часто сталкиваетесь с падением приложения, поэтому сделайте тест, чтобы подтвердить мои подозрения. Когда ваше приложение работает, измените ориентацию экрана и сделайте это пару раз, через несколько минут, предпочтительно, когда в выполнении какой-либо работы участвует Progress Dialog. Это может привести к сбою приложения, которое должно сообщить нам, что ошибка вызвана тем, что диалоговое окно Progress не закрывается правильно.

Моя теория: Когда вы меняете ориентацию, Android создаст новый вид. Вы, вероятно, получаете сбои, потому что ваш фоновый поток пытается изменить состояние старого. (Это может также быть проблема, потому что ваш фоновый поток не в потоке пользовательского интерфейса)

...