Speaking of ViewPager cached pages with preloading vs. lazy loading. Well, I seem to, but not quite. A vague feeling
ViewPager caches pages with preloading
Caching and preloading are two different things that I used to confuse.
Cached and preloaded cached pages are served for preloading. You can load it directly when you cache it and then preload it.
setOffscreenPageLimit
When configuring ViewPager, you can set setOffscreenPageLimit to set the amount of cache and preload, but I was wrong.
When setOffscreenPageLimit (2)
Point!! Caches, caches 2 pages to the left and 2 pages to the right of the current page so there should be 5 pages if you count yourself
Point!! Preloading loads the last two in the direction of the jump
For example, if you jump from 1 to 3, then 4.5 is preloaded. If you jump from 4 to 2, then 1 is preloaded.
The reason the cache caches the left and right sides is so that it can preload from left to right, preload from right, and vice versa.
Preloading problem
mViewPager.setOffscreenPageLimit(0); Is useless, the source code is at least 1. This leads to the problem that the ViewPager must be preloaded, even if you want it not to be loaded
If the page is TAB = 1, the Fragment will run out of time, call the interface there, initialize it, etc. 5 pages on each side of 6 are returned, and 5 pages after 6 are preloaded (all requesting interfaces, initializing pages, etc.), which is very memory consuming and can’t be reclaimed. Cause OOM
ViewPager source
populate
The ViewPager code for the Adapter is all in the populate () method. So the point is this method.
There are five important ways that populate () :
StartUpdate Ready adaptation (unimportant),
InstantiateItem Creates item data,
DestroyItem destroyItem
SetPrimaryItem Sets display of the current item.
FinishUpdate completes the adaptation
ViewPager +fragment So item = fragments, all of these methods in FragmentPagerAdapter. In Java
- InstantiateItem Sets fragment invisible when item data is created (i.e. cache fragment not visible)
- SetPrimaryItem Sets the current item display
- FinishUpdate completes the adaptation and calls the Fragment lifecycle when it completes the adaptation
conclusion
1. When setPrimaryItem (set display of the current item) is clicked, the Fragment is set to be visible and other fragments are notfragment.setUserVisibleHint();
2. The Fragment lifecycle is called when adaptation is complete
3. SetUserVisibleHint () is called before the Fragment’s life cycle, and is not part of the Fragment’s life cycle
Lazy loading
The purpose of lazy loading is to prevent the ViewPager from being preloaded, causing the Fragment to request interface initialization there, etc.
Or — only load the current page when the page is visible. Stop all loading in progress when the page is not visible.
Implement BaseFragment
- SetUserVisibleHint loads data when the page is visible and stops loading when the page is not
- Because setUserVisibleHint is called before the Fragment life cycle, anything that uses the Fragment will flash back when the child Fragment is loading the network data request. So you have to make a judgment call
Whether isViewCreated onCreateView
You also have to manually call the setUserVisibleHint method in onCreateView
- But this is still buggy, and setUserVisibleHint is called several times, because it’s preloaded, cached, and onCreate. so
Only called when the page state changes. Visible –> not visible or not visible –> Visible so you have to first save the page is currently visible, and then the state changes, in the call
- Because the setUserVisibleHint method is not a method in the Fragment lifecycle. This method is not used when the Fragment page jumps, so it should be called manually in onResume () and onPause()
- Even there are bugs. When a page is multi-layered, only the first Fragment will run properly. Later layers of ViewPager will still preload
A layer of ViewPager + Fragment inside a layer of ViewPager + Fragment.
Solution: the inner layer must determine whether its parentFragment is visible or not, and then load it itself
- There’s also a bug, which is that sometimes the inner Fragment doesn’t load when it’s supposed to load, so you have to manually distribute it
It’s the same when you stop