android - Handling screen rotation in WebView -
my web app works great in chrome handles configuration changes (such screen rotation) excellent. preserved.
when loading web app webview
in android app web app loses state on screen orientation change. partially preserve state, i.e. preserves data of <input>
form elements, javascript variables , dom manipulation gets lost.
i webview behave way chrome does, i.e. preserving state including javascript variables. should noted while chrome , webview derives same code base chrome not internally use webview.
what happens on screen orientation change activity (and eventual fragments) gets destroyed subsequently recreated. webview
inherits view
, overrides methods onsaveinstancestate
, onrestoreinstancestate
handling configuration changes hence automatically saves , restores contents of html form elements back/forward navigation history state. state of javascript variables , dom not saved , restored.
proposed solutions
there have been few proposed solutions. of them non-working, preserving partial state or in other ways suboptimal.
assigning webview id
webview
inherits view
had method setid
can declared in layout xml file using android:id
attribute in declaration of <webview>
element. necessary state saved , restored, state partially restored. restores form input elements not javascript variables , state of dom.
onretainnonconfigurationinstance , getlastnonconfigurationinstance
, onretainnonconfigurationinstance
deprecated since api level 13.getlastnonconfigurationinstance
forcing screen orientation
an activity can have screen orientation forced setting screenorientation
attribute <activity>
element in androidmanifest.xml
file or via setrequestedorientation
method. undesired breaks expectation of screen rotation. deals change of screen orientation , not other configuration changes.
retaining fragment instance
does not work. calling method setretaininstance
on fragment retain fragment (it not destroyed), hence instance variables of fragment preserved, does destroy fragment's view hence webview
gets destroyed.
manually handling configuration changes
the configchanges
attribute can declared activity
in androidmanifest.xml
file android:configchanges="orientation|screensize"
handle configuration changes preventing them. works, prevents activity getting destroyed hence webview
, contents preserved. has been discouraged , said used last resort solution may cause app break in subtle ways , buggy. method onconfigurationchanged
gets called when configchanges
attribute set.
mutablecontextwrapper
i heard mutablecontextwrapper
can used, haven't evaluated approach.
savestate() , restorestate()
webview
have methods savestate
, restorestate
. note accoriding documentation savestate
method no longer stores display data webview whatever means. either way these methods not seem preserve state of webview.
webviewfragment
the webviewfragment
convenience fragment wraps webview
can going less boilerplate code, listfragment
. not additional state preserving preserve state.
question
is there real solution problem of webview
getting destroyed , losing state upon configuration changes? (such screen rotation)
a solution fully preserves state including javascript variables , dom manipulation. solution clean , not built on hacks or deprecated methods.
after researching , trying out different approaches have discovered have come believe optimal solution.
it uses setretaininstance
retain fragment instance along addview
, removeview
in oncreateview
, ondestroyview
methods prevent webview
getting destroyed.
mainactivity.java
public class mainactivity extends activity { private static final string tag_fragment = "webview"; @override protected void oncreate(final bundle savedinstancestate) { super.oncreate(savedinstancestate); webviewfragment fragment = (webviewfragment) getfragmentmanager().findfragmentbytag(tag_fragment); if (fragment == null) { fragment = new webviewfragment(); } getfragmentmanager().begintransaction().replace(android.r.id.content, fragment, tag_fragment).commit(); } }
webviewfragment.java
public class webviewfragment extends fragment { private webview mwebview; public webviewfragment() { setretaininstance(true); } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view v = inflater.inflate(r.layout.fragment_webview, container, false); linearlayout layout = (linearlayout)v.findviewbyid(r.id.linearlayout); if (mwebview == null) { mwebview = new webview(getactivity()); setupwebview(); } layout.removeallviews(); layout.addview(mwebview, new linearlayout.layoutparams(viewgroup.layoutparams.match_parent, viewgroup.layoutparams.match_parent)); return v; } @override public void ondestroyview() { if (getretaininstance() && mwebview.getparent() instanceof viewgroup) { ((viewgroup) mwebview.getparent()).removeview(mwebview); } super.ondestroyview(); } private void setupwebview() { mwebview.loadurl("https:///www.example.com/"); } }
Comments
Post a Comment