Android Webviews, saving the state when changing activity? - android

I have a number of different webviews, all in their own activity.
When a menu item is pressed a new activity loads and so does it's webview.
Now clicking between activities reloads each webview, is there a way so that when changing activities the web page doesn't reload and it remembers where the user was?
Thanks

You can use WebView method saveState()/restoreState() and save it to activity onRestore bundle and use saved value in onCreate method if the previous Activity will be destroyed.
You can use similar method which is described here (but used for only configuration change):
http://www.devahead.com/blog/2012/01/preserving-the-state-of-an-android-webview-on-screen-orientation-change/

Related

Which one to use NavUtils.navigateUpFromSameTask() vs. onBackPressed()

I have two activities A and B. The A has a ListFragment which uses LoaderManager, whereas B activity shows a details about the item selected in the A's ListFragment. I've just noticed that when I use a back button to get from the B back to the A, the position in the ListFragment preserve, but when I use the up button (left-point caret) in the action bar, the A activity is recreated and thus position in list view is lost.
I would like fix this issue, but I am not sure about the best way how to do it right.
I come up with this solutions:
a) Use onBackPressed()
Replace the default implementation for the android.R.id.home (the up action bar button) in the B activity, and instead of the NavUtils.navigateUpFromSameTask(this) function call the onBackPressed() activity method. I've tested it and it works.
b) Keep use NavUtils.navigateUpFromSameTask(this)
But implement the onSaveInstanceState and restore listView position during onCreate method of the ListFragment used by the A activity. (I've not tested this approach yet)
Which of this solutions is better? Or is there any other (much more better) solution?
Solution a) is pretty simple and straight forward, but b) is probably better because the default implementation of the up caret is used.
Any ideas are welcome. Thanks.
Solution c is the correct option. First, though, an explanation of the problem with solution a.
There is absolutely no point in having two back buttons in your Activity. Furthermore, option a actually breaks the up button. The point of the up button is to provide a way for users to stay within your app when they have landed in your app from an outside source. For example, if you land on activity B from an outside activity C and if you are using your option a, then pressing "up" in activity B will result in activity C being shown. The behavior you would want would be for activity A to be shown.
As you can see, solution b is on the right track. You definitely want to go up to A and not back to C. However, simply storing the state in onSaveInstanceState will not cause the state to be retained. This is because onSaveInstanceState only gets called if your application may be killed by the system. It is not guaranteed to be called if your application was destroyed manually, and it certainly won't be called when a new instance of your Activity is created. If the Intent starts a new activity, then it will not have its state restored from the other activity.
There solution, then, is that you must write anything persistent to a shared preference file (or a custom persistent alternative). When doing this you can guarantee that all instances of an Activity share the same state across multiple tasks so long as their onResume (or wherever you restore state) is called. OR:
If you know exactly how you want your navigation to work, you can avoid writing everything to persistent state by using a combination of Intent flags and Activity task affinities. If you want to use the same activity as up even if you navigate into the application from an outside source, then you can leave your Activity A's affinity as default (linked to the application) and use something like Intent.FLAG_ACTIVITY_CLEAR_TOP.
Personally, I'd try the Intent flag approach first and failing that fall back to writing the state persistently. You just don't really want scroll location sitting on persistent storage if you can avoid it..
check out this presentation: https://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android. It answers to all of your problems.

Webview saving state of page

I have a small problem with a webview I'm using. I'm trying to use the webview to allow the user to fill out a registration form. This works fine when the user completes the form in one session but should the user lock their phone, the webview activity is destroyed.
I have two activities in memory, one of which is quite memory intensive. The problem I believe I'm having is that because this other activity requires more memory than the webview, the webview is destroyed.
I'm fine with this to a degree, but I would really like to be able to save the current state of the web page so the user doesn't have to submit all of their details again. Is there anyway I can do this.
Thanks
try it :-
You can use WebView method saveState()/restoreState() and save it to activity onRestore bundle and use saved value in onCreate method if the previous Activity will be destroyed.
You can use similar method which is described here (but used for only configuration change):
http://www.devahead.com/blog/2012/01/preserving-the-state-of-an-android-webview-on-screen-orientation-change/
We have run into a similar issue. We have an activity with a webview.
We want the user to input 3 fields on a form in the web view, then launch a new activity (camera) to take a picture. When we get the picture back, and using javascript we insert the picture into the currently active webview form. It all works great 99.9% of the time. However, in some odd scenarios which are difficult to reproduce, while the camera activity is active, the webview activity behind it gets destoryed. saveState / restoreState only partially restores the webview. The 3 form fields that the user had inputted but not submitted when we launched the camera are now lost. They do not get saved by webview.saveState. Also, some javascript state on the page is lost too.
To work around this we added a javascript method to the page and invoke it from the app on saveInstanceState. Then after we restore the state, we invoke another javascript method on the webview page to put the state back. It is a pain in the but and requires work for each form you need to do that to, but it works.
I hope future versions of Android webview.saveState save it exactly as it was before the activity gets destroyed. Alternatively it would be great if you mark an activity as critical to your app and only allow that activity to be destroyed if your app is not the current app the user is working with.
try WebView.addJavascriptInterface, when Activity.onPause, call javascript method in page by loadUrl("javascript:..."), and in web page, call native method that provided by WebView.addJavascriptInterface to save data. is this what you want?
An activity can be destroyed when back key is pressed; when the screen is rotated (is faster destroy the activity and recreate that resort all the graphic elements); or when is posible that it will not active in a few time (lock the phone, press home key or other application is started).
You need to do that #Ixx suggest in his comment : Android webView saveState
Save the data of your application with something like
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
/// save your things, e.g.
outState.putString("name", name);
}
And recover, it exists, in the method onCreate
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// if it is a new activity
if (savedInstanceState == null) {
// initialize vars, e.g.
name = "Unknown";
}
// if is a call after detroy the activity
else {
// recover vars, e.g.
name = savedInstanceState.getString("name");
}
}

View state at fragment on backstack with retaininstance = true

I have got loader in fragment and it loads data on background. After data are loaded, I fill edittexts with that informations. Problem is that if user changes something in edittexts and rotate screen, onLoadFinished is called again and edittexts are replaced with loaded information. I solve this by adding help variable, if data was already loaded .. But when i replace this fragment with other, rotate screen back and forth and press back button, edittexts are empty. Fragment is set to retain instance true. It looks like views lost its state when fragment is on backstack. Anyone familiar with this?
You shouldn't use the retain state.
But the proper way to do so it to save the save using the Bundle and restore it when you recreate the activity (onCreate Bundle is not new).
Please review the link I've sent you it includes a very specific example.
from the android dev guide:
To properly handle a restart, it is important that your activity
restores its previous state through the normal Activity lifecycle, in
which Android calls onSaveInstanceState() before it destroys your
activity so that you can save data about the application state. You
can then restore the state during onCreate() or
onRestoreInstanceState().
Android Rotation Change

Switch between WebView activity retain state (without reloading)

i want to switch between activities that use WebView layout.
Here is the scenario
First, i call a WebView activity (say, SecondActivity) from first activity, with an intent containing URL string. Using that string, the so-called activity load the webpage until done.
I then switch back to the first activity by calling startActivity(firstActivity) inside the
Afterwards, when i try to switch back to the SecondActivity, the webpage is reloaded. It seems that the state of the SecondActivity is not saved and method loadUrl(url) is called again.
To switch back to the first activity you could just call finish() in the second activity?
The state of an activity when switching from one to another is not possible to maintain. This is because of how the Activity lifecycle works, when an Activity is returned to from another, the onCreate is called again reloading all your views, or whatever code you have in your onCreate, which is probably configuring all your views.

Wizard-style activities and onSaveInstanceState

I implemented several activities in a "wizard-style", that is, there's a next and a previous button at the bottom to navigate between them using:
Intent NextActivityIntent = new Intent(v.getContext(), FormN.class);
startActivity(NextActivityIntent);
The problem I'm facing is that when I go back to an Activity, the fields completed previously are empty.
The question is, is there a simpler way to keep displaying the field values other than intercepting the onSaveInstanceState and onRestoreInstanceState events and save/restore every field manually ?
Use startActivityForResult instead of startActivity. The previous activity and its state would remain in the stack. For going back from your current activity use finish().
Ideally, you should code for onSaveInstanceState in case the phone gets re-oriented. Doesn't matter if you lock your phone orientation though.

Categories

Resources