- Android — Fragments
- Fragment Life Cycle
- Fragment lifecycle
- How to use Fragments?
- Types of Fragments
- Android Fragments Common Queries & Common Mistakes
- getSupportFragmentManager and getChildFragmentManager
- Callback from DialogFragment, ChildFragment, BottomSheetFragment to parent fragment
- Fragments when using ViewPager and adapters FragmentStateAdapter and FragmentPagerAdapter which one one to use when
- amodkanthe/ViewPagerTest
- Contribute to amodkanthe/ViewPagerTest development by creating an account on GitHub.
- FragmentTransaction add vs replace
- Fragment receivers, broadcasts and memory leaks
- Fragment BottomBarNavigation and drawer how to handle these
- Android: используем Fragments для оптимизации интерфейса
Android — Fragments
A Fragment is a piece of an activity which enable more modular activity design. It will not be wrong if we say, a fragment is a kind of sub-activity.
Following are important points about fragment −
A fragment has its own layout and its own behaviour with its own life cycle callbacks.
You can add or remove fragments in an activity while the activity is running.
You can combine multiple fragments in a single activity to build a multi-pane UI.
A fragment can be used in multiple activities.
Fragment life cycle is closely related to the life cycle of its host activity which means when the activity is paused, all the fragments available in the activity will also be stopped.
A fragment can implement a behaviour that has no user interface component.
Fragments were added to the Android API in Honeycomb version of Android which API version 11.
You create fragments by extending Fragment class and You can insert a fragment into your activity layout by declaring the fragment in the activity’s layout file, as a element.
Prior to fragment introduction, we had a limitation because we can show only a single activity on the screen at one given point in time. So we were not able to divide device screen and control different parts separately. But with the introduction of fragment we got more flexibility and removed the limitation of having a single activity on the screen at a time. Now we can have a single activity but each activity can comprise of multiple fragments which will have their own layout, events and complete life cycle.
Following is a typical example of how two UI modules defined by fragments can be combined into one activity for a tablet design, but separated for a handset design.
The application can embed two fragments in Activity A, when running on a tablet-sized device. However, on a handset-sized screen, there’s not enough room for both fragments, so Activity A includes only the fragment for the list of articles, and when the user selects an article, it starts Activity B, which includes the second fragment to read the article.
Fragment Life Cycle
Android fragments have their own life cycle very similar to an android activity. This section briefs different stages of its life cycle.
Fragment lifecycle
Here is the list of methods which you can to override in your fragment class −
onAttach()The fragment instance is associated with an activity instance.The fragment and the activity is not fully initialized. Typically you get in this method a reference to the activity which uses the fragment for further initialization work.
onCreate() The system calls this method when creating the fragment. You should initialize essential components of the fragment that you want to retain when the fragment is paused or stopped, then resumed.
onCreateView() The system calls this callback when it’s time for the fragment to draw its user interface for the first time. To draw a UI for your fragment, you must return a View component from this method that is the root of your fragment’s layout. You can return null if the fragment does not provide a UI.
onActivityCreated()The onActivityCreated() is called after the onCreateView() method when the host activity is created. Activity and fragment instance have been created as well as the view hierarchy of the activity. At this point, view can be accessed with the findViewById() method. example. In this method you can instantiate objects which require a Context object
onStart()The onStart() method is called once the fragment gets visible.
onResume()Fragment becomes active.
onPause() The system calls this method as the first indication that the user is leaving the fragment. This is usually where you should commit any changes that should be persisted beyond the current user session.
onStop()Fragment going to be stopped by calling onStop()
onDestroyView()Fragment view will destroy after call this method
onDestroy()onDestroy() called to do final clean up of the fragment’s state but Not guaranteed to be called by the Android platform.
How to use Fragments?
This involves number of simple steps to create Fragments.
First of all decide how many fragments you want to use in an activity. For example let’s we want to use two fragments to handle landscape and portrait modes of the device.
Next based on number of fragments, create classes which will extend the Fragment class. The Fragment class has above mentioned callback functions. You can override any of the functions based on your requirements.
Corresponding to each fragment, you will need to create layout files in XML file. These files will have layout for the defined fragments.
Finally modify activity file to define the actual logic of replacing fragments based on your requirement.
Types of Fragments
Basically fragments are divided as three stages as shown below.
Single frame fragments − Single frame fragments are using for hand hold devices like mobiles, here we can show only one fragment as a view.
List fragments − fragments having special list view is called as list fragment
Fragments transaction − Using with fragment transaction. we can move one fragment to another fragment.
Источник
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
Источник
Android: используем Fragments для оптимизации интерфейса
Добрый день. Сегодня я хотел бы показать вам небольшой и достаточно простой пример использования Fragments. Я надеюсь он будет полезен тем, кто только начал знакомиться с принципами работы Fragments. Изначально, фрагменты были реализованы начиная с Android 3.0 для более динамичного проектирования пользовательских интерфейсов.
Вкратце, Fragment схож с Activity, у них обоих есть свой собственный жизненный цикл. Однако Fragment не может существовать вне Activity. Можно использовать для одного и того же Activity разные Fragments что придает гибкость и вариативность в процессе разработки.
Больше про Fragments можно прочесть здесь:
Fragments. Android Developer
Перейдем же наконец к практике. Напишем небольшую тренировочную программу, в которой будут использоваться фрагменты. При вертикальном положении экрана сначала будет выведен статический список ссылок и при нажатии на ссылку, будет запускаться Activity, отображающее содержимое веб-страницы по выбранной ссылке. При горизонтальном положении экрана, список ссылок и содержимое веб-страницы будут размещаться во Fragments и отображаться одновременно. Схема работы приложения выглядит следующим образом:
Напишем класс FragmentActivity, именно с него начинается работа приложения:
Далее необходимо создать layout в файле fragment.xml для вертикальной и горизонтальной ориентации экрана, который используется в классе FragmentActivity. Для горизонтальной ориентации определим два фрагмента, каждый будет занимать по половине ширины экрана устройства. Содержимое файла /res/layout-land/fragment.xml для горизонтальной ориентации экрана:
Содержимое файла /res/layout/fragment.xml для вертикальной(портретной) ориентации экрана:
Опишем layout файл /res/layout/fragment_detail_activity.xml для Activity, которое будет отображать содержимое веб-страницы в вертикальной(портретной) ориентации:
Сам класс Activity. В нем считываем полученную через extras ссылку и отображаем в WebView содержимое веб-страницы. Данное Activity вызывается в вертикальной ориентации:
Класс FragmentList самый объемный, но не сложный в реализации. В функции onListItemClick мы проверяем наличие FragmentDetail с WebView. Если такой фрагмент существует, то вызываем его функцию goToLink(String link), которая загружает веб-страницу. В противном случае, если фрагмента не существует, то вызывается FragmentDetailActivity, в которое передается ссылка через extras.
Опишем класс FragmentDetail, он будет служить для отображения содержимого веб-страницы в WebView. В частности, отображением занимается функция goToLink(String link), она вызывается в классе FragmentList.
Ну вот и все. Теперь запустим наше приложение. Результат работы должен быть следующим:
Спасибо за внимание.
UPDATE 1:
Спасибо пользователю vtimashkov за дельное замечание, которое находится в первом комментарии к статье. Ниже приведу код, решающий данную проблему,.
Итак, для начала внесем в файл AndroidManifest следующие изменения:
Это позволит нам контролировать изменение ориентации экрана в FragmentDetailActivity. Далее изменим функциональность класса FragmentDetailActivity. Сохраняем текущую ссылку в переменную currentLink. Функция onConfigurationChanged вызывается при смене ориентации экрана. В ней, проверяем, если мы попали с вертикального режима в горизонтальный, то запускаем FragmentActivity и передаем в него текущую ссылку.
И наконец наш FragmentActivity. Сперва проверяем, получили ли мы ссылку в extras. Если да, то это означает, что мы перешли в FragmentDetailActivity в горизонтальный режим и теперь отображаем содержимое веб-страницы в.
Источник