PEEE802.11

モバイルソフトウェアエンジニアの備忘録

WebView.saveState()のJavaDocの解釈

WebView.saveState()は、WebViewの状態をActivity破棄前に保存するためのメソッドである。が、どうもJavaDocがもやもやする。

WebView  |  Android Developers

Saves the state of this WebView used in Activity.onSaveInstanceState(Bundle).

これはわかる。

Please note that this method no longer stores the display data for this WebView.

the display dataってなに。唐突にtheとか言われても。それに、no longerって前はthe display dataとやらを保存してたのか。

The previous behavior could potentially leak files if restoreState(Bundle) was never called.

The previous behaviorってなに。ここでも唐突にtheとか言われる。しかもleakするfilesってなに。

対となるrestoreState()を見ると、

WebView  |  Android Developers

Restores the state of this WebView from the given Bundle. This method is intended for use in Activity.onRestoreInstanceState(Bundle) and should be called to restore the state of this WebView.

わかる。

If it is called after this WebView has had a chance to build state (load pages, create a back/forward list, etc.) there may be undesirable side-effects.

要は、保存してた状態から別の状態をbuildした後に復元しようとすると思わぬ副作用が発生する、ということだろうか。まあわかる。

Please note that this method no longer restores the display data for this WebView.

またもやthe display dataとno longer。わからん。

このthe display dataとやらは、WebViewの他のメソッド含む上記ページJavaDoc内では他に一切出てこない。それとも自分が無知なだけで、WebViewというかブラウザの文脈でthe display dataと言えばみんな知っているものなのだろうか。

なんだか悔しいのでソースコードを見てみると、WebView.savePicture()restorePicture()にthe display dataへの言及がある。これらのメソッドは@deprecatedかつ@hideなので公式JavaDocには含まれていない。

core/java/android/webkit/WebView.java - platform/frameworks/base - Git at Google

    /**
     * Saves the current display data to the Bundle given. Used in conjunction
     * with {@link #saveState}.
     * @param b a Bundle to store the display data
     * @param dest the file to store the serialized picture data. Will be
     *             overwritten with this WebView's picture data.
     * @return {@code true} if the picture was successfully saved
     * @deprecated This method is now obsolete.
     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
     */
    @Deprecated
    @UnsupportedAppUsage
    public boolean savePicture(Bundle b, final File dest) {
        checkThread();
        return mProvider.savePicture(b, dest);
    }

    /**
     * Restores the display data that was saved in {@link #savePicture}. Used in
     * conjunction with {@link #restoreState}. Note that this will not work if
     * this WebView is hardware accelerated.
     *
     * @param b a Bundle containing the saved display data
     * @param src the file where the picture data was stored
     * @return {@code true} if the picture was successfully restored
     * @deprecated This method is now obsolete.
     * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
     */
    @Deprecated
    @UnsupportedAppUsage
    public boolean restorePicture(Bundle b, File src) {
        checkThread();
        return mProvider.restorePicture(b, src);
    }

それぞれBundleFileをパラメータに取り、saveState()restoreState()と一緒に使われて、Bundleにはthe display dataを、Fileにはシリアライズした画像を保存・復元するらしい。the display dataの詳細は書いていないが、具体的な処理はmProviderWebViewProviderインターフェース)に委譲されているので、それぞれのWebView提供具象クラス内で処理されるそれぞれのthe display dataがあるのだろう。また、saveState()でleakすると言っていたfilesはおそらくこの画像ファイルのことだろう。Activityが破棄される前にFileとしてシリアライズした画像を保存して、そのままアプリ自体が終了してしまった場合、復元の機会がなくFileはストレージに残ったままになる。no longer save/restore the display dataと言っているのは、savePicture()/restorePicture()がdeprecatedになる前と比べているのだろう。

以下のコミットが@hideJavaDocに追加したコミットで、ついでにsaveState()/restoreState()のコメントも更新されているのだが、必要最低限中途半端に編集したためメソッドの説明としてこのようなわかりにくい文章になってしまった、というように見える。

Diff - f4912580e6adc90ab37b07b8108c7334f359e317^! - platform/frameworks/base - Git at Google

ドキュメンテーションは大事。

ちなみに、WebViewProviderインターフェースの実装の一つであるchromiumのWebViewのソースコードを追っていくと、AwContents.saveState()でネイティブコードからバイト配列を取得してWEBVIEW_CHROMIUM_STATEというキーでBundleに保存している。savePicture()/restorePicture()はdeprecatedのためfalseを返すのみ。

android_webview/java/src/org/chromium/android_webview/AwContents.java - chromium/src - Git at Google

ネイティブの方は読むのが辛くなってきたので気が向いたら。