Android viewpage notifydatasetchanged No Refresh

Source: Internet
Author: User

Reprint http://www.67tgb.com/?p=624

Recently the project was over and a code share was made. One of the students shared some of their experience in the process of solving problems, feeling benefited. Sort it out and share it with everyone.

It is recommended that you use your own compiled Android OS and virtual machines so that you can debug any component on your Android system. To put it simply, go deep into the Android source code to find answers to your questions. It's a simple thing to say, and it's still a little difficult to actually do. I have also tried to see, not a moment to faint.

So there are targeted to see the source code, the efficiency will be higher.

Don't say much nonsense, first look at the first example.

Viewpager the interface is not refreshed when calling notifydatasetchanged ().

I believe many students who have done Viewpager must have encountered this problem, this is a bug or Android is so designed, we do not discuss. In short, it does affect the implementation of our function.

Many students may choose to reset the adapter adapter for Viewpager, to achieve the purpose of the refresh. But this approach is problematic in most cases.

Tracking Source code:

Why call the method of data update, Viewpager but not update it, we follow up the source of the method to look at.

First look at the super.notifydatasetchanged () of the adapter call, which is transferred to the abstract base class pageradapter.notifydatasetchanged ():

    /**
     * This method should is called by the application if the data backing this adapter have changed
     * and associated views should update.
     */
     Public void notifydatasetchanged () {
        Mobservable.notifychanged ();
    }

Note that when the data attached to the adapter changes, the method should be called to refresh the data. The method calls a mobservable. notifychanged ();

We continue to follow this method into the Datasetobservable class and find such a piece of code:

  /**
     * Invokes {@link datasetobserver#onchanged} on each observer.
     * Called when the contents of the data set has changed.  The recipient
     * would obtain the new contents the next time it queries the data set.
     */
     Public void notifychanged () {
        Synchronized (mobservers) {
            Since OnChanged () is implemented by the app, it could do anything, including
            Removing itself from {@link Mobservers}-and that could cause problems if
            An iterator was used on the ArrayList {@link mobservers}.
            To avoid such problems, just March thru the list in the reverse order.
             for (int i = mobservers. Size ()-1; I >= 0; i--) {
                Mobservers.get (i). onChanged ();
            }
        }
    }

That's not the point. The mobservers type is an abstract class datasetobserver, there are only two non-implemented methods, who use this abstract class, shortcut keys CTRL + ALT + H, among the many callers, We found the Viewpager figure.

Entering Viewpager, we finally found the key method of controlling data change in Viewpager datasetchanged, this method is as follows:

      void datasetchanged () {
        This method only gets called if we observer is attached, so madapter is non-null.
        Boolean needpopulate = mitems. Size () < Moffscreenpagelimit * 2 + 1 &&
                Mitems.size () < Madapter.getcount ();
        int newcurritem = Mcuritem;
        false;
         for (int i = 0; i < mitems.size (); i++) {
            Final ItemInfo II = Mitems. get (i);
            int newpos = madapter.getitemposition (Ii.  Object );
            if (Newpos = = pageradapter.position_unchanged) {
                continue;
            }
            if (Newpos = = Pageradapter.position_none) {
                Mitems.remove (i);
                i--;
                if (!isupdating) {
                    this);
                    true;
                }
                This, ii.position, II. object);
                true;
                if (Mcuritem = = ii.position) {
                    Keep the current item in the valid range
                    Newcurritem = Math. Max (0, Math.min (Mcuritem, Madapter.getcount ()-1));
                    true;
                }
                continue;
            }
            if (ii.position! = Newpos) {
                if (ii.position = = Mcuritem) {
                    Our current item changed position. Follow it.
                    Newcurritem = Newpos;
                }
                II. Position = Newpos;
                true;
            }
        }
        if (isupdating) {
            this);
        }
        Collections. Sort (Mitems, COMPARATOR);
        if (needpopulate) {
            Reset our known page widths; Populate'll recompute them.
            int childCount = Getchildcount ();
             for (int i = 0; i < ChildCount; i++) {
                Final View child = Getchildat (i);
                Final Layoutparams LP = (layoutparams) child.getlayoutparams ();
                if (!lp.isdecor) {
                    Lp. Widthfactor = 0.F;
                }
            }
            false true);
            Requestlayout ();
        }
    }

Focus on this line of code:

int newpos = madapter.getitemposition (Ii.  Object );
   if (Newpos = = pageradapter.position_unchanged) {
         continue ;
   }

The official explanation for GetItemPosition () is:

Called when the host view was attempting to determine if a item ' s position has changed. Returns position_unchanged If the POSITION of the given item has not changed Orposition_none if the item is no longer pres ENT in the adapter.

The default implementation assumes that items would never change position and always returns position_unchanged.

This means that if the position of the item does not change, the position_unchanged is returned. If Position_none is returned, the item for that location does not already exist. The default implementation is to assume that the position of item will never change and return position_unchanged

Solution:

So we can try to modify the adapter notation, overwriting the GetItemPosition () method, when calling Notifydatasetchanged, let the GetItemPosition method artificially return Position_none, Thus achieving the purpose of forcing Viewpager to redraw all item.

The specific code is as follows:

class Searchadapter extends Pageradapter {
    
     Private int mchildcount = 0;
     @Override
      Public void notifydatasetchanged () {         
           Mchildcount = GetCount ();
           Super.notifydatasetchanged ();
     }
     @Override
      Public int object)   {          
           if (Mchildcount > 0) {
           Mchildcount--;
           return Position_none;
           }
           return super.getitemposition (object);
     }
}

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.