"Android" from the source analysis Pageradapter/fragmentpageradapter call notifydatasetchanged () Refresh principle

Source: Internet
Author: User

Believe that the students who have used Viewpager will encounter the call notifydatasetchanged () do not refresh or do not meet the expected problems, today to analyze the ins and outs here. It all has to be said from the Viewpager Setadapter:

    /**     * Set a pageradapter that would supply views for this pager as needed.     *     * @param adapter Adapter to use     *    /public void Setadapter (Pageradapter adapter) {        ... (Omit several lines, same as below) ...        Final Pageradapter oldadapter = madapter;        Madapter = adapter;        Mexpectedadaptercount = 0;        if (madapter! = null) {            if (mobserver = = null) {                mobserver = new Pagerobserver ();            }            Madapter.registerdatasetobserver (mobserver);            ...            ...        }        ...    }

Madapter.registerdatasetobserver (MOBSERVER) uses the Observer pattern here, Mobserver is an example of Pagerobserver, And Pagerobserver is an inner class of Viewpager, which declares the following:

    Private class Pagerobserver extends Datasetobserver {        @Override public        void onChanged () {        // Here the Viewpager datasetchanged () method is called, the same as            datasetchanged ();        }        @Override public        void oninvalidated () {            datasetchanged ();        }    }

So when the Madapter data changes call notifydatasetchanged () refresh, the OnChanged method to Pagerobserver is called, and then the Viewpager () method is called to datasetchanged:

void Datasetchanged () {//This method only gets called if we observer are attached, so madapter is non-null.        Final int adaptercount = Madapter.getcount ();        Mexpectedadaptercount = Adaptercount; Boolean needpopulate = Mitems.size () < Moffscreenpagelimit * 2 + 1 && mitems.size () < adapter        Count;        int newcurritem = Mcuritem;        Boolean isupdating = false;            for (int i = 0; i < mitems.size (); i++) {final ItemInfo II = Mitems.get (i);            Final int newpos = madapter.getitemposition (Ii.object);            if (Newpos = = pageradapter.position_unchanged) {continue;                } if (Newpos = = Pageradapter.position_none) {mitems.remove (i);                i--;                    if (!isupdating) {madapter.startupdate (this);                Isupdating = true;      } madapter.destroyitem (this, ii.position, ii.object);          Needpopulate = true;    ...    } ...    ...        }            ... if (needpopulate) {... setcurrentiteminternal (Newcurritem, False, true);        Requestlayout (); }    }

See here, call Madapter.getitemposition, if the value returned is position_unchanged (the default implementation of Pageradapter), then Needpopulate is false, It is not called to setcurrentiteminternal (which is indirectly called to Instantiateitem (), which is referred to later), so the view is not refreshed. Conversely, if the return value is Position_none, then Needpopulate is true and is called to Setcurrentiteminternal:

   void setcurrentiteminternal (int item, Boolean smoothscroll, Boolean always, int velocity) {        ...            Populate (item);        ...    }

The populate (item) is called to AddNewItem:

    ItemInfo AddNewItem (int position, int index) {        ItemInfo II = new ItemInfo ();        Ii.position = position;        Ii.object = Madapter.instantiateitem (this, position);        Ii.widthfactor = madapter.getpagewidth (position);        if (Index < 0 | | index >= mitems.size ()) {            mitems.add (ii);        } else {            Mitems.add (index, ii);        }        return II;    }


Here we see the call to Madapter.instantiateitem (this, position), and Pageradapter's Instantiateitem did nothing.

So if we're using pageradapter, we need to make a carbon instantiateitem, for example we can write:

@Overridepublic Object Instantiateitem (viewgroup view, int position) {     View.addview (mlist.get (position));     return Mlist.get (position);}

and for Fragmentpageradapter, it made a carbon copy of Instantiateitem:

   @Override public Object Instantiateitem (viewgroup container, int position) {if (mcurtransaction = = null) {        Mcurtransaction = Mfragmentmanager.begintransaction ();        } final Long itemId = Getitemid (position);        Do we already has 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; }

where the default implementation of Getitemid is:

    public long getitemid (int position) {        return position;    }
The subscript for item is the ID of item. In addition, the implementation of Makefragmentname:

    private static String makefragmentname (int viewId, long id) {        return "Android:switcher:" + viewId + ":" + ID;    }
here Makefragmentname is equivalent to assembling this fragment into an identity tag, if not previously added this fragment, namely Mfragmentmanager.findfragmentbytag (name) Return NULL, then call GetItem (position), get fragment, and add this fragment.

Conversely, that is, the fragment has been added before, it will not call GetItem (position), but directly attach on this fragment.


Reference

Http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifydatasetchanged-does-not-work.html









"Android" from the source analysis Pageradapter/fragmentpageradapter call notifydatasetchanged () Refresh principle

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.