ViewPager + fragment how to refresh the cache fragment and viewpagerfragment
Recently, I was working on a project. One function was to flip the pages of answers. Therefore, the next page needs to be cached on this page.
I used
The setOnPageChangeListener method listens and refreshes this page only when sliding to this page:
public void onPageSelected(int position){ ReadFragment fragment= (ReadFragment) fragmentArrayList.get(position); fragment.refresh();}
However, you can use fragmentArrayList. get (position) to obtain the current page only when sliding to this page. If you use this method to obtain the fragment of the next page, a null pointer will be reported. That is to say, the content of the next page cannot be cached and refreshed first.
How can I get the fragment of the next page?
Baidu seems to want
InstantiateItem () Processing in FragmentPagerAdapter. So I looked at its source code:
@Override public Object instantiateItem(ViewGroup container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); // Do we already have this fragment? String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null) { if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment); mCurTransaction.attach(fragment); } else { fragment = getItem(position); if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment); mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } if (fragment != mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; }
It can be seen that the instantiateItem method does not directly get the Fragment from the List, but first finds the corresponding Fragment from the FragmentManager through the Tag. If it can be found, it will not get it from the List, in this case, I added this method to the adapter:
Public ReadFragment getFragment (int position) {String tag = getFragmentTag (mContainer. getId (), position); ReadFragment fragment = (ReadFragment) fm. findFragmentByTag (tag); return fragment ;} /*** call the getFragmentTag method of the FragmentPagerAdapter using the reflection mechanism * @ param viewId * @ param index * @ return */private String getFragmentTag (int viewId, int index) {try {Class <FragmentPagerAdapter> cls = FragmentPagerAdapt Er. class; Class <?> [] ParameterTypes = {int. class, long. class}; Method method = cls. getDeclaredMethod ("makeFragmentName", parameterTypes); method. setAccessible (true); String tag = (String) method. invoke (this, viewId, index); return tag;} catch (Exception e) {e. printStackTrace (); return "";}}
Call the getFragment (int position) method in onPageSelected to cache and refresh the next page when the page is selected.
The getFragment (int position) method actually gets the cached fragment, but you must first ensure that the fragment has been cached in viewpager, although the content has not been refreshed, in this way, no NULL pointer is reported.
An error occurs. onPageSelected is not called when viewPager displays the first page. Therefore, the content on the first page must be refreshed separately and cannot be refreshed in onPageSelected.
Create a method initData () and refresh it in it.
Because viewPager does not call onPageSelected when displaying the first page, the content on the first and second pages cannot be cached first, therefore, the content on the first and second pages must be refreshed separately in initData, and other methods in onPageSelected can be refreshed.
Here we will summarize the ideas:
When you enter the page: refresh the first page and cache the second page.
When turning pages: From the first page to the second page, run onPageSelected ()
In onPagerSelected, call the getFragment (int position) method to obtain the fragment on the next page, that is, the third page, and refresh the cached content.
From the second page to the third page: Execute onPageSelected ()
In onPagerSelected, call the getFragment (int position) method to obtain the fragment on the next page, that is, the fourth page, and refresh the cached content.
Another problem occurs: when the first page is switched to the second page, the system returns and reports a null pointer.
After debugging, I found that the fragment obtained by the getFragment method is null, which is unreasonable. Why? I finally found out that the fragment on the third page is not cached in viewPager, our getFragment is obtained through tag in the cache.
How can we cache the third fragment in viewPager?
By default, viewpager caches the second page on the first page. When the second page is reached, viewpager caches the first and second pages (the cache here means that the component does not mean that the content is the same ), practice has proved that the third page will be cached only when the second page is fully displayed, and onPagerSelected will be called only when the fragment slides to more than half of the screen and our fingers are lifted, if our fingers are not released, they will not be called. When our fingers are released and onPagerSelected is called, the third page will not be cached.
What should I do?
@ Override public void onPageScrollStateChanged (int state ){}
In this paper, we can judge state = 2 in the cache, that is, when the sliding stops, refresh the page, and finally find the same problem.
The original slide stop refers to the sliding of the finger, that is, the finger leaves the screen, rather than the sliding of the fragment.
Do not worry: there is another method:ReadViewPager. setOffscreenPageLimit (2 );
This method can give you an answer.
This method sets the number of caches on both sides of the current page of viewPager,ReadViewPager. setOffscreenPageLimit (2); current pageThere are two caches at left and right. The default value of viewPager isReadViewPager. setOffscreenPageLimit (1 );
So OK ?, It's too early to be happy. A problem occurred while sliding to the fifth page. It was blank. ChangeReadViewPager. setOffscreenPageLimit (3.
(At this time, I only have four fragment entries in total. I use the infinite loop mode and the actual fragment has four.) The actual cache has five fragment entries (the current page has two sides ), is there a problem here.
So I changed fragment to five, and the result was okay.
But there was a problem when turning back the page. After several pages, there was a blank page, so I changed it to 6 fragment. Dizzy.
You also need to refresh the cached content when turning back the page.