Refresh fragment view android

Fragment lifecycle

Each Fragment instance has its own lifecycle. When a user navigates and interacts with your app, your fragments transition through various states in their lifecycle as they are added, removed, and enter or exit the screen.

To manage lifecycle, Fragment implements LifecycleOwner , exposing a Lifecycle object that you can access through the getLifecycle() method.

Each possible Lifecycle state is represented in the Lifecycle.State enum.

By building Fragment on top of Lifecycle , you can use the techniques and classes available for Handling Lifecycles with Lifecycle-Aware Components. For example, you might display the device’s location on the screen using a lifecycle-aware component. This component could automatically start listening when the fragment becomes active and stop when the fragment moves to an inactive state.

As an alternative to using a LifecycleObserver , the Fragment class includes callback methods that correspond to each of the changes in a fragment’s lifecycle. These include onCreate() , onStart() , onResume() , onPause() , onStop() , and onDestroy() .

A fragment’s view has a separate Lifecycle that is managed independently from that of the fragment’s Lifecycle . Fragments maintain a LifecycleOwner for their view, which can be accessed using getViewLifecycleOwner() or getViewLifecycleOwnerLiveData() . Having access to the view’s Lifecycle is useful for situations where a Lifecycle-aware component should only perform work while a fragment’s view exists, such as observing LiveData that is only meant to be displayed on the screen.

This topic discusses the Fragment lifecycle in detail, explaining some of the rules that determine a fragment’s lifecycle state and showing the relationship between the Lifecycle states and the fragment lifecycle callbacks.

Fragments and the fragment manager

When a fragment is instantiated, it begins in the INITIALIZED state. For a fragment to transition through the rest of its lifecycle, it must be added to a FragmentManager . The FragmentManager is responsible for determining what state its fragment should be in and then moving them into that state.

Beyond the fragment lifecycle, FragmentManager is also responsible for attaching fragments to their host activity and detaching them when the fragment is no longer in use. The Fragment class has two callback methods, onAttach() and onDetach() , that you can override to perform work when either of these events occur.

The onAttach() callback is invoked when the fragment has been added to a FragmentManager and is attached to its host activity. At this point, the fragment is active, and the FragmentManager is managing its lifecycle state. At this point, FragmentManager methods such as findFragmentById() return this fragment.

onAttach() is always called before any Lifecycle state changes .

The onDetach() callback is invoked when the fragment has been removed from a FragmentManager and is detached from its host activity. The fragment is no longer active and can no longer be retrieved using findFragmentById() .

onDetach() is always called after any Lifecycle state changes .

Note that these callbacks are unrelated to the FragmentTransaction methods attach() and detach() . For more information on these methods, see Fragment transactions.

Fragment lifecycle states and callbacks

When determining a fragment’s lifecycle state, FragmentManager considers the following:

  • A fragment’s maximum state is determined by its FragmentManager . A fragment cannot progress beyond the state of its FragmentManager .
  • As part of a FragmentTransaction , you can set a maximum lifecycle state on a fragment using setMaxLifecycle() .
  • A fragment’s lifecycle state can never be greater than its parent. For example, a parent fragment or activity must be started before its child fragments. Likewise, child fragments must be stopped before their parent fragment or activity.

Caution: Avoid using the tag to add a fragment using XML, as the tag allows a fragment to move beyond the state of its FragmentManager . Instead, always use FragmentContainerView for adding a fragment using XML. Figure 1. Fragment Lifecycle states and their relation both the fragment’s lifecycle callbacks and the fragment’s view Lifecycle .

Figure 1 shows each of the fragment’s Lifecycle states and how they relate to both the fragment’s lifecycle callbacks and the fragment’s view Lifecycle .

As a fragment progresses through its lifecycle, it moves upward and downward through its states. For example, a fragment that is added to the top of the back stack moves upward from CREATED to STARTED to RESUMED . Conversely, when a fragment is popped off of the back stack, it moves downward through those states, going from RESUMED to STARTED to CREATED and finally DESTROYED .

Upward state transitions

When moving upward through its lifecycle states, a fragment first calls the associated lifecycle callback for its new state. Once this callback is finished, the relevant Lifecycle.Event is emitted to observers by the fragment’s Lifecycle , followed by the fragment’s view Lifecycle , if it has been instantiated.

Читайте также:  Android studio google usb driver не устанавливается

Fragment CREATED

When your fragment reaches the CREATED state, it has been added to a FragmentManager and the onAttach() method has already been called.

This would be the appropriate place to restore any saved state associated with the fragment itself through the fragment’s SavedStateRegistry . Note that the fragment’s view has not been created at this time, and any state associated with the fragment’s view should be restored only after the view has been created.

This transition invokes the onCreate() callback. The callback also receives a savedInstanceState Bundle argument containing any state previously saved by onSaveInstanceState() . Note that savedInstanceState has a null value the first time the fragment is created, but it is always non-null for subsequent recreations, even if you do not override onSaveInstanceState() . See Saving state with fragments for more details.

Fragment CREATED and View INITIALIZED

The fragment’s view Lifecycle is created only when your Fragment provides a valid View instance. In most cases, you can use the fragment constructors that take a @LayoutId , which automatically inflates the view at the appropriate time. You can also override onCreateView() to programmatically inflate or create your fragment’s view.

If and only if your fragment’s view is instantiated with a non-null View , that View is set on the fragment and can be retrieved using getView() . The getViewLifecycleOwnerLiveData() is then updated with the newly INITIALIZED LifecycleOwner corresponding with the fragment’s view. The onViewCreated() lifecycle callback is also called at this time.

This is the appropriate place to set up the initial state of your view, to start observing LiveData instances whose callbacks update the fragment’s view, and to set up adapters on any RecyclerView or ViewPager2 instances in your fragment’s view.

Fragment and View CREATED

After the fragment’s view has been created, the previous view state, if any, is restored, and the view’s Lifecycle is then moved into the CREATED state. The view lifecycle owner also emits the ON_CREATE event to its observers. Here you should restore any additional state associated with the fragment’s view.

This transition also invokes the onViewStateRestored() callback.

Fragment and View STARTED

It is strongly recommended to tie Lifecycle-aware components to the STARTED state of a fragment, as this state guarantees that the fragment’s view is available, if one was created, and that it is safe to perform a FragmentTransaction on the child FragmentManager of the fragment. If the fragment’s view is non-null, the fragment’s view Lifecycle is moved to STARTED immediately after the fragment’s Lifecycle is moved to STARTED .

When the fragment becomes STARTED , the onStart() callback is invoked.

Note: Components such as ViewPager2 set the maximum Lifecycle of offscreen fragments to STARTED .

Fragment and View RESUMED

When the fragment is visible, all Animator and Transition effects have finished, and the fragment is ready for user interaction. The fragment’s Lifecycle moves to the RESUMED state, and the onResume() callback is invoked.

The transition to RESUMED is the appropriate signal to indicate that the user is now able to interact with your fragment. Fragments that are not RESUMED should not manually set focus on their views or attempt to handle input method visibility.

Downward state transitions

When a fragment moves downward to a lower lifecycle state, the relevant Lifecycle.Event is emitted to observers by the fragment’s view Lifecycle , if instantiated, followed by the fragment’s Lifecycle . After a fragment’s lifecycle event is emitted, the fragment calls the associated lifecycle callback.

Fragment and View STARTED

As the user begins to leave the fragment, and while the fragment is still visible, the Lifecycle s for the fragment and for its view are moved back to the STARTED state and emit the ON_PAUSE event to their observers. The fragment then invokes its onPause() callback.

Fragment and View CREATED

Once the fragment is no longer visible, the Lifecycle s for the fragment and for its view are moved into the CREATED state and emit the ON_STOP event to their observers. This state transition is triggered not only by the parent activity or fragment being stopped, but also by the saving of state by the parent activity or fragment. This behavior guarantees that the ON_STOP event is invoked before the fragment’s state is saved. This makes the ON_STOP event the last point where it is safe to perform a FragmentTransaction on the child FragmentManager .

As shown in figure 2, the ordering of the onStop() callback and the saving of the state with onSaveInstanceState() differs based on API level. For all API levels prior to API 28, onSaveInstanceState() is invoked before onStop() . For API levels 28 and higher, the calling order is reversed.

Figure 2. Calling order differences for onStop() and onSaveInstanceState() .

Fragment CREATED and View DESTROYED

After all of the exit animations and transitions have completed, and the fragment’s view has been detached from the window, the fragment’s view Lifecycle is moved into the DESTROYED state and emits the ON_DESTROY event to its observers. The fragment then invokes its onDestroyView() callback. At this point, the fragment’s view has reached the end of its lifecycle and getViewLifecycleOwnerLiveData() returns a null value.

At this point, all references to the fragment’s view should be removed, allowing the fragment’s view to be garbage collected.

Fragment DESTROYED

If the fragment is removed, or if the FragmentManager is destroyed, the fragment’s Lifecycle is moved into the DESTROYED state and sends the ON_DESTROY event to its observers. The fragment then invokes its onDestroy() callback. At this point, the fragment has reached the end of its lifecycle.

Читайте также:  Прошивка samsung a310f android 7

Additional resources

For more information related to the fragment lifecycle, see the following additional resources.

Guides

Blogs

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.

Источник

Fragments

A Fragment represents a reusable portion of your app’s UI. A fragment defines and manages its own layout, has its own lifecycle, and can handle its own input events. Fragments cannot live on their own—they must be hosted by an activity or another fragment. The fragment’s view hierarchy becomes part of, or attaches to, the host’s view hierarchy.

Modularity

Fragments introduce modularity and reusability into your activity’s UI by allowing you to divide the UI into discrete chunks. Activities are an ideal place to put global elements around your app’s user interface, such as a navigation drawer. Conversely, fragments are better suited to define and manage the UI of a single screen or portion of a screen.

Consider an app that responds to various screen sizes. On larger screens, the app should display a static navigation drawer and a list in a grid layout. On smaller screens, the app should display a bottom navigation bar and a list in a linear layout. Managing all of these variations in the activity can be unwieldy. Separating the navigation elements from the content can make this process more manageable. The activity is then responsible for displaying the correct navigation UI while the fragment displays the list with the proper layout.

Figure 1. Two versions of the same screen on different screen sizes. On the left, a large screen contains a navigation drawer that is controlled by the activity and a grid list that is controlled by the fragment. On the right, a small screen contains a bottom navigation bar that is controlled by the activity and a linear list that is controlled by the fragment.

Dividing your UI into fragments makes it easier to modify your activity’s appearance at runtime. While your activity is in the STARTED lifecycle state or higher, fragments can be added, replaced, or removed. You can keep a record of these changes in a back stack that is managed by the activity, allowing the changes to be reversed.

You can use multiple instances of the same fragment class within the same activity, in multiple activities, or even as a child of another fragment. With this in mind, you should only provide a fragment with the logic necessary to manage its own UI. You should avoid depending on or manipulating one fragment from another.

Next steps

For more documentation and resources related to fragments, see the following.

Getting Started

Further topics

Videos

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.

Источник

Android Fragments Common Queries & Common Mistakes

Fragment class in Android is used to build dynamic User Interfaces. Fragment should be used within the Activity. A greatest advantage of fragments is that it simplifies the task of creating UI for multiple screen sizes. A activity can contain any number of fragments.

Now this meaning of fragment sounds good and easy, right? But there is lot more involved, this article covers main needs and common mistakes while using Fragments.

I am assuming you are having basic knowledge of Fragment and Fragment lifecycle callbacks also I am assuming you know how implement communication between two fragments this article goes beyond that

So here are a few obstacles related to fragments some of you must have faced already, some of you might face later.

  • FragmentManager: getSupportFragmentManager and getChildFragmentManager. Which one to use when and avoid memory leaks while using them.
  • Callback from DialogFragment, ChildFragment, BottomSheetFragment to parent fragment.
  • Fragments when using ViewPager and when to use FragmentStateAdapter vs FragmentPagerAdapter.
  • When to use FragmentTransaction add vs replace ?
  • Fragment receivers, broadcasts and memory leaks.
  • Fragment BottomBarNavigation and drawer. How to handle these?
  • commit() and commitAllowingStateLoss()
  • Fragment option menus.
  • Fragment getActivity(), getView() and NullPointers Exceptions.
  • onActivityResult with nested fragments.
  • Fragment and Bundle.
  • Back Navigation.

Whoa . see its a big list, reply in comment if anyone wish to add something more to the list.

getSupportFragmentManager and getChildFragmentManager

FragmentManager is class provided by the framework which is used to create transactions for adding, removing or replacing fragments.

  • getSupportFragmentManager is associated with Activity consider it as a FragmentManager for your Activity .

So whenever you are using ViewPager, BottomSheetFragment and DialogFragment in an Activity you will use getSupportFragmentManager

  • getChildFragmentManager is associated with fragment.

Whenever you are ViewPager inside Fragment you will use getChildFragmentManager

Here is official link for this for better understanding.

Now coming to common mistakes people do when they are using ViewPager inside a Fragment they pass getSupportFragmentManager which is fragment manager for Activity and it causes issues as such memory leaks, ViewPager not updated properly sometimes etc.

Most important issue caused by using getSupportFragmentManager in Fragment is memory leak, let me tell you how? Your Fragment has stack of fragments which is used by ViewPager or any other thing and all these fragments stack is in activity since you used getSupportFragmentManager , now if close your Parent fragment it will be closed but it will not be destroyed because all child Fragments are in activity and they are still in memory which does not allow to destroy Parent Fragment hence causing leak. It will not just leak parent fragment but also leak all child fragments since none of them can be cleared from heap memory. So never try to use getSupportFragmentManager in a Fragment

Читайте также:  Хороший чат для андроид

Callback from DialogFragment, ChildFragment, BottomSheetFragment to parent fragment

This is very common issue people face when they use BottomSheetFragment or DialogFragment or ChildFragment.

Add a child fragment

Another example bottomSheetFragment

Now suppose you want callback from these child fragments to parent fragments . Most of people create connection between two fragments using activity, few people pass interface listeners as a parameter to fragment which really a bad practice and one should avoid this. Best way calling getParentFragment() from your child fragment to create a call back this is very simple way consider example below.

then setting callback to parent fragment add following code in child fragment.

thats it you can give a callback to your parent fragment now easily.

Using same way you can create a callback from child fragment inside ViewPager to parent fragment who is holding ViewPager.

Fragments when using ViewPager and adapters FragmentStateAdapter and FragmentPagerAdapter which one one to use when

FragmentPagerAdapter stores the whole fragment in memory, and could increase a memory overhead if a large amount of fragments are used in ViewPager . FragmentStatePagerAdapter only stores the savedInstanceState of fragments, and destroys all the fragments when they lose focus.

So when your is going to have many Fragments use FragmentStateAdapter if ViewPager is going to have less than three fragments use FragmentPagerAdapter.

Commonly faced issues

Update ViewPager not working:

People always come across the issue remember ViewPager fragments are managed by FragmentManager either from Fragment or Activity and this FragmentManager holds instance of all ViewPager Fragments.

So when people say ViewPager is not refreshed it’s nothing but old instances of fragments are still being hold by FragmentManager. So you need to find out why FragmentManger is holding instance of Fragments is there any leak or not ideally to refresh ViewPager following code works if it is not you are doing something wrong

Access current Fragment from ViewPager:

This is also very common issue we come across. For this people either create array list of fragments inside adapter or try to access fragment using some tags according to me both methods are not reliable. FragmentStateAdapter and FragmentPagerAdapter both provides method setPrimaryItem this can be used to set current fragment as below.

I am leaving a Github link below to this simple ViewPager project so that everyone can understand better.

amodkanthe/ViewPagerTest

Contribute to amodkanthe/ViewPagerTest development by creating an account on GitHub.

FragmentTransaction add vs replace

In our Activity we have a container and inside this container we display our Fragments

add will simply add fragment to container suppose you add FragmentA and FragmentB to container. Container will have FragmentA and FragmentB both and suppose if container is FrameLayout fragments are added one above the other. replace will simply replace a fragment on top of container so if I call create FragmentC now and call replace FragmentB which was on top will removed from container unless you are not calling addToBackStack and now FragmentC will be on top.

So which one to use when. replace removes the existing fragment and adds a new fragment . This means when you press back button the fragment that got replaced will be created with its onCreateView being invoked. Whereas add retains the existing fragments and adds a new fragment that means existing fragment will be active and they wont be in ‘paused’ state hence when a back button is pressed onCreateView is not called for the existing fragment(the fragment which was there before new fragment was added). In terms of fragment’s life cycle events onPause, onResume, onCreateView and other life cycle events will be invoked in case of replace but they wont be invoked in case of add .

Use replace fragment if don’t need to revisit current fragment and current fragment is not require anymore. Also if your app has memory constraints use replace instead of add.

Fragment receivers, broadcasts and memory leaks

Mistakes people commonly do when using receivers inside a fragment forgot to unregister receiver in onPause or OnDestroy. If you are registering fragment to listen to receiver inside onCreate or OnResume you will have to unregister it inside onPause or onDestroy otherwise it will cause memory leak

Also if have multiple fragments listening to same broadcast receiver make sure you register in onResume and unregister in onPause. Because if you use onCreate and onDestroy for register and unregister other fragments will not receive the broadcast as this fragment is not destroyed

Fragment BottomBarNavigation and drawer how to handle these

When we are using BottomBarNavigation and NavigationDrawer people face issues like fragments recreated, same fragment is added multiple times etc.

So in such case you can use fragment transaction show and hide instead of add or replace.

There is also one beautiful library which take care of navigations and avoid recreation of fragments called FragNav below is link to it

Источник

Оцените статью