Fragment: lazy loading + ViewPager + TabLayout, viewpagertablayout

Source: Internet
Author: User

Fragment: lazy loading + ViewPager + TabLayout, viewpagertablayout
Fragment

When ViewPager opens 1st fragment, it will open 2nd fragment and execute 2nd lifecycles from onCreateView to onResume (2nd fragment will be opened when you click 3rd ...), To avoid too many operations in onCreateViewFragment visible&&First loadLoad data

When Fragment and ViewPager are used together, a method setUserVisibleHint () is taken away in the lifecycle. You can call getUserVisibleHint manually to check that callback () is not called before setUserVisibleHint () in a single Fragment.
How to load resources lazily (two types)

Fragment. setUserVisibleHint ViewPager. addOnPageChangeListener onPageSelected (int position)

First. setUserVisibleHint: the judgment we need to make

Fragment is visible. We can determine whether isVisibleToUser has loaded the View based on setUserVisibleHint, whether the isVisibleToUser has loaded the data by creating its own identification space, and by creating its own identification Space

Writing Method

Write BaseFragment first

Public abstract class BaseFragment extends Fragment {protected Activity mActivity; protected View mRootView; private Unbinder unbinder;/*** description: save the global Context ** @ param context */@ Override public void onAttach (Context context) {super. onAttach (context); mActivity = (Activity) context ;}@ Nullable @ Override public View onCreateView (LayoutInflater inflater, @ Nullable ViewGroup container, @ Nu Llable Bundle savedInstanceState) {mRootView = inflater. inflate (getLayoutId (), container, false); unbinder = ButterKnife. bind (this, mRootView); init (); return mRootView;}/*** @ return returns the layout id of the Fragment */protected abstract int getLayoutId (); /*** note: the initialization operations during view creation are all written in this method */protected abstract void init (); /*** get control object ** @ param id Control id * @ return control object */public View findViewById (int id) {if (GetContentView ()! = Null) {return getContentView (). findViewById (id);} else {return null ;}}/*** Note: return the current View ** @ return view */protected View getContentView () {return mRootView ;} @ Override public void onDestroyView () {super. onDestroyView (); unbinder. unbind ();}}

Write more lazyFragment

/***** Lazy loading of Fragment ** conditions for loading data: * 1. view initialized * 2. the view is visible to the user */public abstract class LazyLoadFragment extends BaseFragment {public boolean isInit = false; // whether the view has initialized public boolean isLoad = false; // whether the view has been loaded/***** initialized */@ Override protected void init () {isInit = true; isCanLoadData ();} /*** determine whether data can be loaded. if data can be loaded */private void isCanLoadData () {if (! IsInit) {// return not initialized;} if (getUserVisibleHint () {// The user can see lazyLoad (); isLoad = true;} else {if (isLoad) {// the user is invisible and has loaded stopLoad () ;}}/ *** when the view is initialized and visible, the data is loaded */public abstract void lazyLoad (); /*** when this view is invisible to users and data has been loaded, If You Need To Stop loading data when switching to another page, override this method to implement */public void stopLoad () {}/ *** instructions: this method is called when the visibility of the current view changes ** @ param isVisibleToUser whether the current view is visible */@ Override public void setUserVisibleHint (boolean isVisibleToUser) {super. setUserVisibleHint (isVisibleToUser); isCanLoadData ();}/*** changes the status of Fragment initialization to false when the view is destroyed */@ Override public void onDestroyView () {super. onDestroyView (); isInit = false; isLoad = false ;}}
Second, Judge by onPageSelected

Disadvantage: onPageSelected is not called for 1st page visits

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {    @Override    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {    }    @Override    public void onPageSelected(int position) {       // TODO       fragment.initData();    }    @Override    public void onPageScrollStateChanged(int state) {    }});
PagerAdapter

There are three types

(1) PagerAdapter Data source: List
 
  
Suitable for carousel images and image viewing (2) FragmentPagerAdapter Data source: List
  
   
(3) FragmentStatePagerAdapter Data source: List
   
  
 
Differences between FragmentPagerAdapter and FragmentStatePagerAdapter

FragmentPagerAdapter: fragmentTransaction () calls depatch (), and the lifecycle goes to onDestroyView (). It is suitable for the main interface with few pages,Only view is recycled and data is retainedFragmentStatePagerAdapter: fragmentTransaction () calls remove (), and the lifecycle goes to onDetach (). It is suitable for multiple pages and multiple data,View and data are recycled, but the onSaveInstance method is also called. bundle may exist.

Use the FragmentStatePagerAdapter to open multiple Fragment:

The first time you enter the page

 0: onAttach 0: onCreate 1: onAttach 1: onCreate 0: onCreateView 0: onViewCreated 0: onActivityCreated 0: onStart 0: onResume 1: onCreateView 1: onViewCreated 1: onActivityCreated 1: onStart 1: onResume

From Page 0th to page 1st

2: onAttach2: onCreate2: onCreateView2: onViewCreated2: onStart2: onResume

From Page 1st to page 2nd, the page 0th will be killedOnDetach

3: onAttach3: onCreate0: onPause0: onStop0: onDestroyView0: onDestroy0: onDetach3: onCreateView3: onViewCreated3: onActivityCreated3: onStart3: onResume

From Page 1st to page 0th

2: onPause2: onStop2: onDestroyView2: onDestroy2: onDetach

FragmentPagerAdapter is used to route the invisible page lifecycle to onDestroyView.

3: onAttach3: onCreate0: onPause0: onStop0: onDestroyView3: onCreateView3: onViewCreated3: onActivityCreated3: onStart3: onResume
Whether the adapter is external or internal

The adapter should not hold the context of the Activity; otherwise, memory leakage may occur as much as possible. OOMInternal, According to Google's example

Tab associated with viewpager

TabLayout. setupWithViewPager (viewpager); pass in viewpager

The setupWithViewPager method clears the tab in the populateFromPagerAdapter and calls getPageTitle. Therefore, the correct way to set the tab is to spell CharSequence in getPageTitle.Link

//... Omit Part of the Code // process the viewpagerif (viewPager! = Null) {mViewPager = viewPager; // ① the following code processes sliding associations. For example, sliding listener // Add our custom OnPageChangeListener to the ViewPager if (mPageChangeListener = null) {mPageChangeListener = new TabLayoutOnPageChangeListener (this);} mPageChangeListener. reset (); viewPager. addOnPageChangeListener (mPageChangeListener); // Now we'll add a tab selected listener to set ViewPager's current item mCurrentVpSelectedListener = new ViewPagerOnTabSelectedListener (viewPager); addO NTabSelectedListener (mCurrentVpSelectedListener); // ② this part of the code can explain why the content of our tab settings will disappear final PagerAdapter adapter = viewPager. getAdapter (); if (adapter! = Null) {// Now we'll populate ourselves from the pager adapter, adding an observer if // autoRefresh is enabled // obtain the adapter set externally to viewpager and reset setPagerAdapter (adapter, autoRefresh) through setPagerAdapter );}...}...} void setPagerAdapter (@ Nullable final PagerAdapter adapter, final boolean addObserver) {if (mPagerAdapter! = Null & mPagerAdapterObserver! = Null) {// If we already have a PagerAdapter, unregister our observer mPagerAdapter. unregisterDataSetObserver (mPagerAdapterObserver);} // register observer mPagerAdapter = adapter; if (addObserver & adapter! = Null) {// Register our observer on the new adapter if (mPagerAdapterObserver = null) {mPagerAdapterObserver = new PagerAdapterObserver ();} adapter. registerDataSetObserver (mPagerAdapterObserver);} // Finally make sure we reflect the new adapter // key code populateFromPagerAdapter ();} void populateFromPagerAdapter () {// remove all tabs. // The previously set tab is the removed removeAllTabs (); if (mPagerAdapter! = Null) {final int adapterCount = mPagerAdapter. getCount (); for (int I = 0; I <adapterCount; I ++) {// re-Add the tab. The content of setText is obtained by getPageTitle in PagerAdapter, therefore, the answer to the question is obvious. AddTab (newTab (). setText (mPagerAdapter. getPageTitle (I), false);} // Make sure we reflect the currently set ViewPager item if (mViewPager! = Null & adapterCount> 0) {final int curItem = mViewPager. getCurrentItem (); if (curItem! = GetSelectedTabPosition () & curItem <getTabCount () {selectTab (getTabAt (curItem ));}}}}
Tab Add title

GetPageTitle (int position) of the adapter returns the title name corresponding to each pager.

Tab to add images

CharSequence of getPageTitle (int position) of the adapter cannot see the image;

Solution: PutTextAllCapsSet to false

 

Style can be set in styles or separately added to xml

Custom tabItem

Add in the activity to prevent the context from being passed to the external Adapter. setupWithViewPager first runs and then adds the view to the for loop. A simple button is switched using selector.

@Overrideprotected void onCreate(Bundle savedInstanceState) {    tabLayout.setupWithViewPager(viewpager);    for (int i = 0; i < tabLayout.getTabCount(); i++){        tabLayout.getTabAt(i).setCustomView(getTabView(i));    }}public View getTabView(int position){   View view = LayoutInflater.from(this).inflate(R.layout.tab_home_bottom, null);   ImageView ivHomeTab = (ImageView) view.findViewById(R.id.iv_home_tab);   ivHomeTab.setImageResource(tabIcons[position]);   return view;}
SetTabMode

TabLayout. MODE_SCROLLABLE follows viewpager to scroll TabLayout. MODE_FIXED fixed Tab. tabGravity. GRAVITY_FILL must be used with TabLayout. MODE_FIXED.

Underline Indicator

The style uses tabIndicatorColor to set the color and tabIndicatorHeight to set the width and height.

Process horizontal/vertical switchover (to be verified)
@Override   public void onSaveInstanceState(Bundle outState) {       super.onSaveInstanceState(outState);       outState.putInt(POSITION,tabLayout.getSelectedTabPosition());   }   @Override   protected void onRestoreInstanceState(Bundle savedInstanceState) {       super.onRestoreInstanceState(savedInstanceState);       viewPager.setCurrentItem(savedInstanceState.getInt(POSITION));   }
How many pagers are saved by ViewPager? Use ViewPager. setOffscreenPageLimit (num)

Retain 2 num + 1 pages not destroyed, that is, when set 1, retain the default value of 1 on both sides, unless you modify the source code

Viewpager + PagerAdapter + TabLayout
ViewPager viewpager = (ViewPager) findViewById(R.id.viewpager);        viewpager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) {            @Override            public Fragment getItem(int position) {                Fragment fragment = null;                switch (position) {                    case 0:                        fragment = new FragmentZero();                        break;                    case 1:                        fragment = new FragmentOne();                        break;                    case 2:                        fragment = new FragmentTwo();                        break;                    case 3:                        fragment = new FragmentThree();                        break;                    case 4:                        fragment = new FragmentFour();                        break;                    case 5:                        fragment = new FragmentFive();                        break;                }                return fragment;            }            @Override            public int getCount() {                return 6;            }            @Override            public CharSequence getPageTitle(int position) {                switch (position){                    case 0:                        return "0";                    case 1:                        return "1";                    case 2:                        return "2";                    case 3:                        return "3";                    case 4:                        return "4";                    default:                        return "0";                }            }        });TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout);tabLayout.setupWithViewPager(viewpager);

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.