Lazy loading optimization

Posted by imarockstar on Thu, 10 Feb 2022 17:09:19 +0100

Catalog introduction

  • 1. What is lazy loading

    • 1.1 what is preloading

    • 1.2 introduction to lazy loading

    • 1.3 lazy loading summary

  • 2. What are the lazy loading cases in practical application

    • 2.1 ViewPager+Fragment combination

    • 2.2 analysis source code

  • 3. Source code related to setoffsetscreenpagelimit (int limit) in viewpager

  • 4. About ViewPager and Fragment loading

    • 4.1 problems encountered

    • 4.2 main ideas and practices

    • 4.3 code case display

    • 4.4 onLazyLoad() loading data conditions

    • 4.5 Fragment method setUserVisibleHint

  • 5. Why do lazy loading fragments inherit BaseFragment

 

 

1. What is lazy loading

  • 1.1 what is preloading

    • The combination of ViewPager+Fragment is also common in daily development. It can be used to switch and display different types of pages. This kind of control combination can be used in consulting, shopping, finance, social networking and other types of apps we see every day

    • The ViewPager control has a unique preloading mechanism, that is, by default, one page on the left and right sides of the current page will be loaded to facilitate the user to display more smoothly when sliding and switching to the adjacent interface.

    • The number of preloaded pages can be set through the setOffscreenPageLimit(int limit) of ViewPager, and the limit pages adjacent to the current page will be preloaded into memory

  • 1.2 introduction to lazy loading

    • Lazy loading, in fact, is to delay loading. It is to wait until the UI of the page is displayed to the user, and then load the data of the page (from the network, database, etc.), rather than relying on the ViewPager Preloading Mechanism to load the data of two or three or even more pages in advance. The initialization speed of the user's Activity can also be improved This lazy loading method has been / is being adopted by many apps.

    • However, through the source code of the ViewPager method setoffsetscreenpagelimit (int limit), it can be found that the ViewPager ensures that at least one page adjacent to the left and right sides will be preloaded through certain logical judgment, that is, the effect of lazy loading cannot be achieved through simple configuration.

  • 1.3 lazy loading summary

    • When the page is visible, the current page is loaded.

    • If there is no open page, it will not be preloaded.

    • To put it bluntly, lazy loading is to request data when it is visible.

2. What are the lazy loading cases in practical application

  • 1.1 the combination of viewpager + fragment uses lazy loading

  • 1.2 H5 web page using lazy loading

 

3. Source code related to setoffsetscreenpagelimit (int limit) in viewpager

  • 3.1 the source code is as follows:

//Default number of cached pages (constant)
private static final int DEFAULT_OFFSCREEN_PAGES = 1;
​
//Number of cached pages (variable)
private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES;
​
public void setOffscreenPageLimit(int limit) {
    //When the limit number we manually set is less than the default value of 1, the limit value will be automatically assigned to the default value of 1 (i.e. DEFAULT_OFFSCREEN_PAGES)
    if (limit < DEFAULT_OFFSCREEN_PAGES) {
        Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "+ DEFAULT_OFFSCREEN_PAGES);
        limit = DEFAULT_OFFSCREEN_PAGES;
    }
​
    if (limit != mOffscreenPageLimit) {
        //After the previous interception judgment, set the limit value to moffscreen pagelimit for
        mOffscreenPageLimit = limit;
        populate();
    }
}
  • 3.2 analysis of source code

    • ViewPager uses certain logical judgment to ensure that at least one page adjacent to the left and right sides will be preloaded, that is, the effect of lazy loading cannot be achieved through simple configuration.

4. About ViewPager and Fragment loading

  • 4.1 problems encountered

    • When using ViewPager (or other containers) in combination with multiple fragments, ViewPager will load the current page one page at a time by default. Even if setting setofflimit (0) has no effect, it will also be preloaded. In this way, the data of the page we can't see is also loaded, which greatly reduces the performance and wastes initialization resources. However, we use lazy loading technology, which allows users to load their data only when they see the page, which greatly improves the efficiency.

  • 4.2 main ideas and practices

    • The main method is setUserVisibleHint() in the fragment. This method will be executed before onCreateView(). It will also be called when the fragment changes the visible state in viewPager. This method will be called when the fragment changes from visible to invisible or from invisible to visible. Use getUserVisibleHint() to return whether the fragment is visible.

    • In BaseMVPLazyFragment, lazyLoad() method needs to be called once in onActivityCreated() and setUserVisibleHint() methods. If lazyLoad() is only called in setUserVisibleHint(), when the default home page is loaded first, there will be no data display in the first display of the home page of viewPager. Only after switching can there be data. Because the setUserVisible() of the front page fragment is called before onActivityCreated (), when isPrepared is false, the home page fragment fails to invoke the onLazyLoad() method to load the data.

  • 4.3 code case display

public abstract class BaseMVPLazyFragment<T extends IBasePresenter> extends BaseMVPFragment<T> {
    /**
    * Fragment View loaded tag
    */
    protected boolean isViewInitiated;
    /**
    * Fragment Tags visible to users
    */
    protected boolean isVisibleToUser;
    /**
    * Lazy load
    */
    protected boolean isDataInitiated;
​
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
​
    /**
    * The first step is to change the isViewInitiated flag
    * When the onViewCreated() method is executed, it indicates that the View has been loaded. At this time, change the isViewInitiated flag to true and call the lazyLoad() method
    */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        isViewInitiated = true;
        //Just Fragment onCreateView,
        //In addition, lazyLoad() is called once here
        prepareFetchData();
        //lazyLoad();
    }
​
    /**
    * Step two
    * This method will be executed before onCreateView()
    * Called when the fragment in viewPager changes the visible state
    * This method is called when the fragment changes from invisible or invisible to visible
    */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        this.isVisibleToUser = isVisibleToUser;
        prepareFetchData();
    }
​
    /**
    * Step 4: define the abstract method fetchData(), and the specific work of loading data is handed over to the subclass
    */
    public abstract void fetchData();
​
    /**
    * Step 3: Double mark judgment in lazyLoad() method, and then load the data
    * The first method
    * When lazy loading is called, getUserVisibleHint() will return whether it is visible or not
    * This is the key to lazy loading of fragments. onLazyLoad() will be called to load data only when fragments are visible
    */
    private void lazyLoad() {
        if (getUserVisibleHint() && isViewInitiated && !isDataInitiated) {
            fetchData();
            isDataInitiated = true;
        }
    }
​
    /**
    * The second method
    * Call lazy load
    */
    public void prepareFetchData() {
        prepareFetchData(false);
    }
​
    /**
    * Step 3: Double mark judgment in lazyLoad() method, and then load the data
    */
    public void prepareFetchData(boolean forceUpdate) {
        if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
            fetchData();
            isDataInitiated = true;
        }
    }
}
  • 4.4 onLazyLoad() loading data conditions

    • getUserVisibleHint() will return whether it is visible or not, which is the key to lazy loading of fragments. onLazyLoad() will be called to load data only when fragments are visible.

    • The isPrepared parameter is set to true when the system calls onActivityCreated. At this time, the onCreateView method has been called (generally, we execute findviewbyid and other methods in this method) to ensure that the onLazyLoad() method will not report null pointer exceptions.

    • Islazyload ensures that the initData method of BaseFragment will not be called repeatedly when the ViewPager switches back and forth. onLazyLoad is called only once in the whole life cycle of the Fragment. Islazyload = true is executed immediately after the onLazyLoad() method is called for the first time.

    • Then inherit this BaseMVPLazyFragment and implement onLazyLoad() method. It will automatically control the loading of data only when the fragment is displayed

  • 4.5 Fragment method setUserVisibleHint

    • The source code is as follows

    • This method is used to set whether the UI of the Fragment is visible to the user. When the page is visible / invisible to the user, the system will call back this method.

    • We can rewrite this method, and then make relevant logical judgment according to the isVisibleToUser parameter of the callback to achieve the effect of lazy loading. For example, if isVisibleToUser==true, it means that the current Fragment is visible to the user, and then load the page data.

5. Why do lazy loading fragments inherit BaseFragment

  • 5.1 benefits of inheriting BaseFragment

    • This BaseFragment is the most basic base class. It carries out some bottom-level settings and defines abstract functions: such as binding layout files, initializing view controls, initializing data, and initializing toolbars

    • So the lazy load LazyLoadFragment is basically separated. The coupling degree is quite low. It can basically be used in this way.

    • Another point is that some fragments do not need lazy loading, so they can directly inherit the BaseFragment class; Directly inheriting BaseMVPLazyFragment class that needs lazy loading

 

Topics: Android