Сохраняет ли WebView saveState() переменные/среду Javascript?

Перерыл много тем, так и не нашел ответа на свой вопрос. Я работаю над приложением Android, которое использует WebView.

Я использую onSaveInstanceState() и onRestoreInstanceState() для сохранения состояния WebView следующим образом:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    webView.saveState(savedInstanceState);
}

а также

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    webView.restoreState(savedInstanceState);
}

У меня также есть это в моем onCreate():

public void onCreate(Bundle savedInstanceState) {
    ... other code ...
    if(savedInstanceState != null){
        webView.saveState(savedInstanceState);
    }else{
        webView.loadUrl("http://mypage");
    }
}

Проблема: кажется, что восстановление WebView вообще не восстанавливает Javascript переменных/окружения/рабочей области. Когда приложение уничтожается в фоновом режиме, а затем восстанавливается, весь Javascript исчезает со всеми объектами/переменными. Код javascript имеет пространство имен, то есть window.utilitiesPack, window.eventHandlers, window.automation и т. д., и они не определены. Также используются JQuery и другие плагины javascript: все они кажутся неопределенными после состояния восстановления. В основном весь Javascript не восстанавливается.

Может ли кто-нибудь подтвердить или опровергнуть, что это так на самом деле (Javascript не сохранен)? Если все рабочее пространство Javascript не сохраняется, то что именно сохраняет WebView.saveState()? Есть ли простой/элегантный способ использовать существующий API для сохранения объектов Javascript?

//======================================================

Update1: Проблема остается. Самая существенная трудность заключается в следующем:

Запускаю Камеру Intent на результат. Когда снимок сделан, приложение возвращается к WebView активности и должно использовать Javascript для обновления HTML5 LocalStorage некоторыми переменными данных.

Основное действие с WebView уничтожается, пока отображается действие камеры, поэтому, когда мы возвращаемся к WebView, больше нет Javascript и функций, которые я могу вызывать из кода Android. Это происходит каждый раз Galaxy S3. Это все еще происходит на других телефонах, но не каждый раз при фотографировании.

Не знаю, что здесь делать. Каким-то образом я должен сделать основное действие с WebView, чтобы сохранить состояние, пока изображение делается с намерением камеры. Кто-нибудь знает, как этого можно достичь?


person user2113581    schedule 27.02.2013    source источник
comment
Может ли кто-нибудь подтвердить или опровергнуть, что это так на самом деле - разве вы только что не подтвердили это, попробовав и увидев, что это действительно происходит?   -  person millimoose    schedule 27.02.2013
comment
(Документация, кажется, подразумевает, что то, что сохранено, является WebBackForwardList.)   -  person millimoose    schedule 27.02.2013
comment
Разве вы только что не подтвердили это, попробовав и увидев, что это действительно происходит? Я просто не могу поверить, что весь Javascript не сохранен. Я надеюсь, что я что-то не понимаю, потому что если это так, это такое ограничение для приложений, которые используют веб-страницы со сложной функцией javascript.   -  person user2113581    schedule 27.02.2013
comment
Правильно ли я понял: WebBackForwardList на самом деле сохраняет материал Javascript?   -  person user2113581    schedule 27.02.2013
comment
Хорошо, я понимаю, что вы имеете в виду. Спасибо за вашу помощь.   -  person user2113581    schedule 27.02.2013
comment
Привет @ user2113581, это проблема, с которой сталкивается все больше людей. Не могли бы вы написать решение своего вопроса вместо комментария, который вы оставили ниже?   -  person Michael Alan Huff    schedule 26.03.2014
comment
@ user2113581: не могли бы вы предоставить свое решение для кода? У меня та же проблема, что и у вас, я не смог заставить WebView сохранить состояние текущей страницы, а также пространство javascript. Спасибо   -  person Richard Le    schedule 21.07.2014


Ответы (2)


Информации нашёл очень мало, только вот эта строчка:

Обратите внимание, что этот метод больше не хранит отображаемые данные для этого WebView. Предыдущее поведение потенциально могло привести к утечке файлов, если restoreState(Bundle) никогда не вызывался.

и эта строка:

Возвращает ту же копию списка назад/вперед, которая использовалась для сохранения состояния.

в javadoc для WebView.saveState(Bundle).

person diyism    schedule 09.07.2013
comment
Спасибо за ваш ответ. Прошло некоторое время с тех пор, как я столкнулся с этой проблемой, и поэтому я забыл о своем вопросе здесь. Я отмечаю ваш ответ как правильный, так как он есть. Для тех, кто сталкивается с той же проблемой: я решил ее, определив webView в контексте приложения, а не в контексте действия. Теперь все работает как положено. Единственная проблема с этим подходом заключается в том, что вам придется переопределить onJsAlert() и onJsConfirm(), чтобы заставить работать alert()/confirm(). Также ‹select› больше не будет работать, поэтому реализуйте свой собственный html select. В остальном он работает отлично, и js не теряется. - person user2113581; 11.07.2013
comment
Это лишь частичное решение, поскольку ОС Android имеет разрешение полностью завершить процесс вашего приложения, находясь в другом приложении (например, в приложении камеры), поэтому сохранение состояния веб-просмотра в экземпляре приложения не решит эту проблему. Это может произойти, например, при нехватке системных ресурсов. - person Steven Mark Ford; 01.03.2016

Как прокомментировал пользователь 2113581, перемещение WebView в контекст приложения, а не в действие, является потенциальным решением. В нем все еще есть все подводные камни, о которых упоминал пользователь 2113581, в том числе <select> не работает (поскольку он создает окно, но контекст приложения не имеет токена окна).

Я расширил свое приложение для управления своим веб-просмотром...

Мое приложение.java:

public class MyApplication extends Application {
  private WebView mWebView;
  private boolean mWebViewInitialized;
  // ...

  @Override public void onCreate() {
    super.onCreate();
    mWebView = new WebView(this);
    mWebViewInitialized = false; // we do some initialization once in our activity.
  }

  public WebView getWebView() { return mWebView; }
  public boolean isWebViewInitialized() { return mWebViewInitialized; }
  public void setWebViewInitialized(boolean initialized) {
    mWebViewInitialized = initialized;
  }
}

В нашей деятельности:

@Override protected void onCreate(Bundle savedInstanceState) {
  // ...
  MyApplication app = (MyApplication) getApplication();
  mWebView = app.getWebView();
  if (!app.isWebViewInitialized()) { 
    /* first time initialization */ 
    app.setWebViewInitialized(true);
  }
}

Наконец, в своей деятельности вы захотите добавить mWebView в представление контейнера (FrameLayout или подобное) во время события жизненного цикла, которое имеет смысл. Вам нужно будет удалить его из контейнера, когда действие будет приостановлено или остановлено. Я использовал onResume и onPause с хорошими результатами.

person Ryan Schultz    schedule 26.03.2014
comment
Умный! Вы пробовали подобную стратегию и для iOS? - person eugene; 10.04.2015
comment
Это лишь частичное решение, поскольку ОС Android имеет разрешение полностью завершить процесс вашего приложения, находясь в другом приложении (например, в приложении камеры), поэтому сохранение состояния веб-просмотра в экземпляре приложения не решит эту проблему. Это может произойти, например, при нехватке системных ресурсов. - person Steven Mark Ford; 01.03.2016
comment
Проблема, которую я обнаружил при таком подходе, заключается в том, что Webview теперь имеет ApplicationContext, а не ActivityContext. Это работает нормально, пока вы не попытаетесь выполнить вызов подтверждения (...) из JavaScript, после чего приложение вылетит. Кажется, что когда Webview должен открыть диалоговое окно, он пытается передать контекст в ActivityContext, и в этой реализации это не удается. - person BruceHill; 05.07.2016