It seems that onSaveInstanceState when overridden in a custom View is not called if the activity that created the View also has onSaveInstanceState overridden. Why is this and is there a way to call both? Is one better to use than the other? Since not all Views are custom I find that it might be necessary to have the activity call onSavedInstanceState too.
In addition if you call it in the Custom View, how do you tell the activity to not perform the time consuming tasks, upon rotation, that were used to create the View in onCreate in the first place? The onSaveInstanceState in the View was used to stop the activity from performing time consuming tasks again and again.
You have to add super.onSaveInstanceState() in your overridden method, it calls this method in all attached fragments and views.
It is a good practice to call super.onSaveInstanceState() every time you override it.
Related
I got a fragment, that should create some files, iterate through the contactbook and some other pretty long tasks.
The fragment is a pretty simple "Hey, please wait" fragment with a label and a progressbar. I used factory pattern to pass arguments to this fragment.
My fragments code is comparable to the solution of this question, only with other parameters and members. In the onStart-method I want to do my long tasks, but strangely it starts the code before I see my view, which should be created by the onCreateView-method first, if I remember the Fragment-lifecycle correct.
Is this a side effect of Factory Pattern or what am I missing here? What would be the best solution here, so that the view is actually shown before he starts my long code execution?
OnStart is called when the activity is becoming visible to the user. onCreateView will create your view but its not visible yet. You should start your long operation in onResume.
Please refer to http://developer.android.com/reference/android/app/Activity.html#onResume()
Basically as Nauman mentioned, often an indication that your activity is ready to be interacted by the user is the onResume. but ideally, use
onWindowFocusChanged(boolean hasFocus)
but keep in mind that this is not part of the normal lifecycle event flow. This method can be also called when dialogs come up in front of the Activity etc
see http://developer.android.com/reference/android/app/Activity.html#onWindowFocusChanged(boolean)
I have thinking some time about this. I have an FragmentActivity in wich I have a FrameLayout and some Fragments change there. Each fragment has different layout and launches different asynctask. My question is :
Where is the best place, I mean best fragment state, to call asynctask ? I mean like I have some textviews in fragment layout and I want them to display text values based on asynctask result. Should I call the asynctask in onCreateView or somewhere else ? Making the call in onCreateView would invoke the asynctask more times as the orientation would change, as I am aware of. So what is the best practice for fragments with asynctask ?
Better to use AsyncTaskLoader instead AsyncTask with fragments
When you create the Asynctask in onCreate it gets called only when the fragment is created. When you call it in onResume it gets called even after the user returns gets a phone message. So it depends on how up to date you want the data.
You could even call it in onViewCreated but it really is up to you. You can also call it in the application object so the asynctask is executed only when the user starts the app.
I'm developing an android tablet application and i need to implement screen orientation (landscape and portrait). when screen orientation changes the fragment asyntactask restarting again. (sometimes application crashing) I need to stop restarting the asynctask and request data again. want to load the existing json data in to the new screen.
any help appreciate.
approch: android:configChanges="keyboardHidden|orientation|screenSize" is not working because of im using a fragment class.
You may find some hack (including muting the configuration changes or retaining the instance) to somehow get it work, but really AsyncTasks are evil and you should stay as far as you can from it most of the time.
If your current AsyncTask's job is to load some data from the network before showing it inside your Fragment, I'd recommend to use an AsyncTaskLoader. The examples in the javadoc should give you a good idea of how to implement it.
This will allow the network request to keep going while you rotate, to notify the UI (i.e. the LoaderManager.LoaderCallbacks) with the result only when it is ready to process it (so not while rotating for example), and will also cache the result so that you don't re-issue the network request each time you need the data.
There are a bunch of 3rd-party libraries trying to address this very common problem too, and Loaders also have their intricacies, but if I understand your use case correctly it should be just what you need.
Don't forget that whatever solution you choose it will have to account for the rotation (activity destroy / recreate) happening before, during and after the load of the data.
It seems that this approach is the less recommended. If you're initializing and executing your AsyncTask within your onCreate() method, I'd suggest using this approach. Basically it consists on saving the data you don't need to restart on a runtime configuration change, so you can handle them afterwards in the onCreate() method and decide which information you want to keep from the previous landscape and which should be restarted.
You can easily avoid the "re-creation" of a fragment, just using the setRetainInstance method on it.
public void setRetainInstance (boolean retain)
Control whether a fragment instance is retained across Activity
re-creation (such as from a configuration change). This can only be
used with fragments not in the back stack. If set, the fragment
lifecycle will be slightly different when an activity is recreated:
•
onDestroy() will not be called (but onDetach() still will be, because
the fragment is being detached from its current activity).
•
onCreate(Bundle) will not be called since the fragment is not being
re-created.
• onAttach(Activity) and onActivityCreated(Bundle) will
still be called.
Reference link
You can use this for example in you onCreateView method, like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
setRetainInstance(true);
// ... more of your code
}
While the Activity that contains the fragment still re-creating, the fragment instance will be the same, and will be reattached to the new activity.
Keep in mind that even with setRetainInstance the onCreateView method will be called always (in orientation change) because the fragment need to inflate the view according to the new space/dimensions, so if you are executing your asynctask from that method, you should consider moving it to the onCreate method (which will only be executed once) to avoid the "re-launching" every orientation change.
Hope it helps.
I am trying to understand on which stage android OS is rendering layouts, in order to be able to access views in my ListView. Thanks
The layouts are created in onCreate():
The entire lifetime of an activity happens between the first call to
onCreate(Bundle) through to a single final call to onDestroy().
The Activity is visible from onStart():
The visible lifetime of an activity happens between a call to
onStart() until a corresponding call to onStop(). During this time the
user can see the activity on-screen
Source: the documentation.
I have a ViewPager with 4 views. View #3 needs to respond to some broadcasted events. Hence, I register a custom BroadcastReceiver in onCreate as described here. This works if I make sure to show view #3, triggering the onCreate event. Otherwise, it doesn't work, obviously.
How can I make sure that onCreate is indeed called for fragments waiting to be shown. I.e. How to force fragment creation?
See comment above. setOffscreenPageLimit is the key.