画面回転するとWebViewの入力内容が破棄される問題ついての解決方法
画面を回転すると、Activityは再生成されます。
その時に保持しているWebViewのHTMLのFORMの内容がクリアされてしまいます。
どうしましょう...?
大抵の場合、
じゃあ、「"android:configChanges" の属性指定で Activity再生成抑止」したらいいんじゃない?といわれますが...
画面回転以外のActivity再生成はどうするの?
物理キーボードがスライドされ有効になった時は?充電ドッグに載せた時は?
Activityが再生成されても問題の無いアプリケーションを作りましょう!
Activity/Fragment再生成時の保存/復元処理には以下のような方法があります。
- Activity#onSaveInstanceStateで保存 / Activity#onCreateで復元
- Activity#onRetainNonConfigurationInstanceで保存 / Activity#getLastNonConfigurationInstanceで復元
- Fragment#onSaveInstanceStateで保存 / Fragment#onCreateで復元
- Fragment#setRetainInstance(true)で、 Fragment が破棄されないようにする。
ActivityのWebView
Activity#onRetainNonConfigurationInstanceで保存 / Activity#getLastNonConfigurationInstanceで復元 する方法で行います。
public class WebViewActivity extends AppCompatActivity {
private View mContent;
private WebView mWebView;
protected boolean mHasSavedInstanceState;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LOGV(TAG, "onCreate()");
mHasSavedInstanceState = (savedInstanceState != null);
// 保存されたWebViewを取得する。
mContent = (View) getLastCustomNonConfigurationInstance();
if (mContent == null) {
// 取得できなかった場合は、Viewを作成する。
LayoutInflater inflater = getLayoutInflater()
.cloneInContext(new MutableContextWrapper(this));
ViewGroup parent = (ViewGroup) getWindow().getDecorView()
.findViewById(Window.ID_ANDROID_CONTENT);
mContent = inflater.inflate(R.layout.activity_webview, parent, false);
} else {
// 取得したViewをsetContentViewする。
MutableContextWrapper context = (MutableContextWrapper) mContent.getContext();
// Change the base context for this ContextWrapper.
context.setBaseContext(this);
}
setContentView(mContent);
mWebView = (WebView) findViewById(R.id.web_view);
}
@Override
public Object onRetainCustomNonConfigurationInstance() {
LOGV(TAG, "onRetainCustomNonConfigurationInstance()");
// WebViewを保存する。
((ViewGroup) findViewById(Window.ID_ANDROID_CONTENT)).removeView(mContent);
return mContent;
}
@Override
protected void onDestroy() {
super.onDestroy();
LOGV(TAG, "onDestroy()");
// Activity破棄の理由を取得
int changingConfigurations = getChangingConfigurations();
LOGV(TAG, "getChangingConfigurations() :" + changingConfigurations + " (" + String.format("0x%08x", changingConfigurations) + ")");
// Activity再作成以外の破棄の場合。
if (changingConfigurations == 0) {
// WebViewを破棄する。
if (mWebView != null) {
mWebView.stopLoading();
mWebView.setWebChromeClient(null);
mWebView.setWebViewClient(null);
unregisterForContextMenu(mWebView);
mWebView.destroy();
mWebView = null;
}
}
}
}
FragmentのWebView
Fragment#setRetainInstance(true)で、 Fragment が破棄されないようにする方法で行います。
public class WebViewFragment extends Fragment{
View mContent;
WebView mWebView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LOGV(TAG, "onCreateView()");
// Activity再生成時にFragmentを破棄させない。
setRetainInstance(true);
// Viewが生成されていない場合に、Viewをインフレートして作成する。
if (mContent == null) {
mContent = inflater.inflate(R.layout.fragment_webview, container, false);
}
return mContent;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
LOGV(TAG, "onViewCreated()");
super.onViewCreated(view, savedInstanceState);
// WebViewがまだ設定されていない場合にメンバー変数へ格納する。
if (mWebView == null) {
mWebView = (WebView) view.findViewById(R.id.web_view);
}
}
@Override
public void onDestroy() {
super.onDestroy();
LOGV(TAG, "onDestroy()");
// Activityの再生成ではない場合には呼ばれる。
// WebViewを破棄する。
if (mWebView != null) {
mWebView.stopLoading();
mWebView.setWebChromeClient(null);
mWebView.setWebViewClient(null);
unregisterForContextMenu(mWebView);
mWebView.destroy();
mWebView = null;
}
}
Fragment#onDestroyは、Activity再生成時でない場合にはちゃんと呼ばれるので、WebViewの破棄の処理を行っおきます。
参考)
- Android WebView handling orientation changes - Stack Overflow http://stackoverflow.com/questions/1002085/android-webview-handling-orientation-changes
- slightfoot/android-web-wrapper https://github.com/slightfoot/android-web-wrapper/tree/48cb3c48c457d889fc16b4e3eba1c9e925f42cfb
- Activity再生成時のデータの保存・復元(Fragment#setRetainInstance) - プログラマってこんなかんじ?? http://daichan4649.hatenablog.jp/entry/20120530/1338367072
GitHub)
granoeste/WebViewFragmentExample https://github.com/granoeste/WebViewFragmentExample