Order of Fragment Lifecycle Methods - java

IF i have multiple fragments in my layout, what exactly is the order in which their lifecycle methods are called? Am i right in thinking Fragment 1's onAttach(), onCreate(), onCreateView() is run first followed by the same three methods for Fragment 2? And then each of the fragments onStart() is called in the order in which the fragments are defined in the layout? If anyone can point me to a resource that clearly defines this ordering it would really help!

Related

onActivityCreated is deprecated what is the alternative [duplicate]

I just saw that onActivityCreated() is going to be deprecated in future. I try to implement LifecycleOwner and LifecycleObserver pattern but I'm not quite sure about what I'm doing here.
I'm using NavigationComponent, which meens :
I have a MainActivity
I have a MainFragment, instanciated as the home fragment
I have multiple fragments that can be accessed from this home fragment
For some reasons I need to know when activity is created from all of these fragments (MainFragment and sub fragments)
From what I've seen until now, I need to :
In the MainActivity, getLifecycle().addObserver(new MainFragment()). And do this for all sub fragments (which is verbose for nothing)
In fragments, implements LifecycleObserver and
#OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
private void onCreateEvent() {
Timber.i("%s MainActivity created", TAG);
}
This seems to work well, but I have some questions :
The syntax addObserver(new MainFragment() disturbs me. It looks like we are creating a new fragment instance, while the fragment is normally instantiated with the navigation defined in the navGraph.
As I said before, if I have my MainFragment with 10 sub fragments, I'll have to declare 11 observers ? Weird
Do I have to clear these observers at some point in the activity lifecycle ?
What is the proper way to implement it ?
EDIT 1:
To answer the question why I need to know when the activity is created :
I need this because I need to access my MainActivity viewmodel (new ViewModelProvider(requireActivity()).get(ViewModel.class). To call requireActivity() or getActivity() I need to know when the activity is created (was easy with onActivityCreated()).
Databinding is implemented with my MainActivity and this viewmodel. The layout of this activity is hosting a loader to show when network requests are performed.
I can perform requests from the MainFragment and from the sub fragments. When I perform a request from one of these fragments I need to enable this loader view, and when I got datas back I need to hide this loader.
And yes, all these fragments are in the graph
You have never needed to wait for onActivityCreated() to call requireActivity() or getActivity() - those are both available as soon as the Fragment is attached to the FragmentManager and hence can be used in onAttach(), onCreate(), onCreateView(), onViewCreated() all before onActivityCreated() is called.
This is one of the reasons why onActivityCreated() was deprecated - it actually has nothing to do with the activity becoming available to the Fragment, nor does it have anything to do with the activity finishing its onCreate() (it, in fact, can be called multiple times - every time the Fragment's view is created, not just once after the first time the Activity finishes onCreate()).
As per the deprecation notice:
use onViewCreated(View, Bundle) for code touching the Fragment's view and onCreate(Bundle) for other initialization.
Those are the recommended replacements, depending on whether the code you had in onActivityCreated() was accessing the Fragment's views or not.
Once you realize that requireActivity() can be called in onAttach(), etc., the rest of the deprecation notice makes more sense:
To get a callback specifically when a Fragment activity's Activity.onCreate(Bundle) is called, register a LifecycleObserver on the Activity's Lifecycle in onAttach(Context), removing it when it receives the Lifecycle.State.CREATED callback.
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
// Register a LifecycleObserver on the Activity's Lifecycle in onAttach()
requireActivity().getLifecycle().addObserver(this);
}
#OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
private void onCreateEvent() {
// Remove the LifecycleObserver once you get a callback to ON_CREATE
requireActivity().getLifecycle().removeObserver(this);
// Then do your logic that specifically needs to wait for the Activity
// to be created
Timber.i("%s MainActivity created", TAG);
}
But, as mentioned above, this is not what you should be doing if you are trying to access a ViewModel at the activity level.

How to share a MediaPlayer object between multiple fragments?

I have set up 1 Main Activity (that extends Activity class) and 2 Fragments (that extends the fragment class).
I've tried setting up an Interface, which is implemented by the 2 fragments. And each fragment implements the particular function from the interface like this:
public stopMusic()
{
mediaplay.release(); // here, the mediaplay object belongs to only the respective fragment
}
Now, I know doesn't work, because the MediaPlayer object is not common to both fragments, i.e it's not being shared among them.
I'm looking to release the mediaplayer object streaming a file in Fragment1.java, if I hit a button from another fragment, like Fragment2java. Likewise, to release the mediaplayer object streaming a file in Fragment2.java, if I hit a button from Fragment1.java.
How can I make this happen? An example code would really help.
Let's say fragment A is the controlling fragment and fragment B is the media player. All communication should be done via the parent Activity. So in fragment B you create 'public interface(s)' which the parent activity implements, then the parent Activity should call the method(s) in fragment B.
Also depending on what you are really doing with the media player or whatever, does that belong in the background as opposed to fragment B?
Note: fragments should be loosely coupled and never communicate from fragment to fragment, always communicate via the parent Activity.
Hope this helps.

v4.app.Fragment when is it created and destroyed?

How exactly v4.app.Fragment works? I have viewPager with 7 Fragments. I was sure that when moving between fragments, depending on the situation each fragment can be automatically destroyed and created. However it seems not to be true.
I decided to play a bit with debugging and set some flag for my Fragment class object, something like
class MyClass extends Fragment {
public boolean myFlag=false;
When I set ex. true somewhere in the code which is run only once (ex. true is set after button click), it seems that this value is true until the app ends. Thus it suggest the object is kept all the time in memory.
However when user moves between Fragments onCreateView and onViewStateRestored methods seems to be called.
And now I feel quite confused. If Fragments are not destroyed, why those methods are executed by Android?
Do I have the guarantee that my Fragment object will be kept always with all fields (when user only moves beteween Fragments and doesn't leave the app)?
If not how should I save and restore its state? public void onSaveInstanceState(Bundle savedInstanceState) method seems to be only run when user left the app, not when user moves between Fragments.
Have you seen any good tutorial concerning ViewPager and Fragments?
And now I feel quite confused. If Fragments are not destroyed, why
those methods are executed by Android?
If you look at this diagram, Fragments do not need to be destroyed to call onCreateView().
Do I have the guarantee that my Fragment object will be kept always
with all fields (when user only moves beteween Fragments and doesn't
leave the app)?
This depends on what you are doing. If your case is dealing with ViewPager it really boils down to what PagerAdapter you use and your ViewPager configuration.
If not how should I save and restore its state? public void
onSaveInstanceState(Bundle savedInstanceState) method seems to be only
run when user left the app, not when user moves between Fragments.
It depends under what conditions you are wanting to restore state. For example, for orientation changes you can call setRetainInstance(true) on the Fragment and the Fragment's state will be preserved when there is a configuration change given your Fragment is not on the backstack.
Have you seen any good tutorial concerning ViewPager and Fragments?
The Android Guide has a good tutorial.
You can re-initialize all the values of a specific fragment in it's onCreate(...) method. So that when ever it is navigated to, it will have the default values that you setup in your onCreate(...) method.
Here are some useful links related to the Implementation of Fragments in a ViewPager:
1. http://thepseudocoder.wordpress.com/2011/10/13/android-tabs-viewpager-swipe-able-tabs-ftw/
2. http://androidtrainningcenter.blogspot.co.il/2012/10/viewpager-example-in-android.html
3. http://manishkpr.webheavens.com/android-viewpager-example/
4. http://thepseudocoder.wordpress.com/2011/10/05/android-page-swiping-using-viewpager/
I hope this helps.

Android: Where to put activity's onCreate() code in a fragment?

I'm converting all my Activities to Fragments so that I can use them in a ViewPager.
I've searched for this but I couldn't find a satisfying answer, so that's why I'm asking it here.
In my Activities, I've written some code in the onCreate() method. I for example call some findViewById()s in order to link some xml-buttons to my Activity. I also make some views invisible in the onCreate(), set an OnClickListener(), fill a TextView with text and remove a Notification, all in the onCreate() method.
My question is: Where should I put this code in the fragment? In the onCreate()? onCreateView()? onActivityCreated()? and why?
Many thanks in advance!
Although Pragnani's answer is close, there's little educational value in it. Besides, there's a more appropriate option to his 2nd statement.
Where should I put this code in the fragment? In the onCreate()?
onCreateView()? onActivityCreated()? and why?
The short answer is: either onCreateView() or onActivityCreated() will do. The view hierarchy won't be created until onCreateView(), so that's the earliest point in the fragment's life cycle that you could inflate the views and attach click listeners etc. Since onActivityCreated() will always be run after onCreateView(), that's a suitable location too. onCreate() may be skipped in favour of the system temporarily detaching the fragment and reattaching it, e.g. when retaining fragments.
Pragnani is correct by pointing out that inflating the views of a fragment is slightly different from inflating views in an activity. More specifically: a fragment does not define a findViewById() method, so you'll need to call it on some other object.
Rather than using getActivity().findViewById(), you'll want getView().findViewById(). The reason for this is that if you use the activity for the view lookups, then you'll get into trouble when multiple fragments with the same view IDs are attached to it. This will be the case if you reuse view ids in the layouts of your various fragments, or if you show two identical fragments that display different data. In both cases, only the first match would ever be returned, whereas you really want to the view to be looked up in the conext of the fragment. That's exactly what getView() returns, the fragment's root view (that you returned in onCreateView()), and thus limits the scope of the lookup appropriately.
1.Left the onCreate empty and just call super.onCreate()
2.Instead of findViewById() use getActivity().findViewById()
always use getActivity() where you need context of the view.
Do all other operations in onCreateview()

Add a new fragment to ViewPager within a FragmentActivity

I have spent the better part of two days searching for an answer that solves my question, I have found plenty that come close but not specific to what I need:
I would like to add a new FragmentActivity to a viewPager from inside a current FragmentActivity by calling the FragmentPageAdapter (or at least, this is how I see I need to solve my problem).
For example: In fragment 1 I would like to press a button to update and replace Fragment 2 with new data, and then set Fragment 2 as the currently viewed fragment.
What you could do is implementing a custom FragmentPagerAdapter or FragmentStatePagerAdapter (If you have lots of more complex fragments).
Documentation: http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
The Adapter handles your contents so whatever calls or operations you wanna make on a certain fragment could be done quite easy from there.
You could pass the adapter itself to every fragment that its holding or just implement listener interfaces so that the fragments can trigger the changes through the adapter.
I hope this helps you out if its still an issue!

Categories

Resources