Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getItem() method is getting called twice when using Fragment Pager Adaptor

Tags:

android

I am using a fragment pager adaptor to instantiate my fragment class.I am able to do so but my problem is that my getItem() method is getting called twice which is creating problem further.can u explain me why it is happening .

    package com.creatiosoft.rssfeed.adaptor;

    import android.content.Context;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.util.Log;

    import com.creatiosoft.rssfeed.utils.RssItem;
    import com.viewpagerindicator.IconPagerAdapter;

    public class NewsFeedsAdapter extends FragmentPagerAdapter implements
            IconPagerAdapter {

        int[] icon = null;
        String[] content = null;
        String[] URLs = null;
        Context cont;

        public NewsFeedsAdapter(FragmentManager fm, Context context) {
            super(fm);
            Log.i("jk", "constructor");
            this.cont = context;
            RssItem newsFeedAppliaction = (RssItem) cont;
            /*
             * Retrieving the values of the Icons and contents from the application
             * class in utils package
             */
            icon = newsFeedAppliaction.getICONS();
            content = newsFeedAppliaction.getCONTENT();
            URLs = newsFeedAppliaction.getURL();

        }

        /** instantiate a new fragment class */
        @Override
        public Fragment getItem(int position) {
            Log.i("yt", "hello" + position);
            return TestFragment.newInstance(position % content.length, cont);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return content[position % content.length].toUpperCase();
        }

        public int getIconResId(int index) {
            return icon[index];
        }

        /** return the no of views on the basis of array items */
        @Override
        public int getCount() {

            Log.i("hi", "length" + content.length);
            return content.length;
        }
    }      

I am calling Adaptor with this code:

NewsFeedsAdapter adapter = new NewsFeedsAdapter(
                getSupportFragmentManager(), getApplicationContext());
        /**
         * get the id of the view pager declared in the xml resource and set the
         * adaptor on the view pager
         */
        ViewPager pager = (ViewPager) findViewById(R.id.pager);
        pager.setAdapter(adapter);
        //pager.setCurrentItem(0);

        /**
         * Tab page indicator class is used to indicate the tabs and is accessed
         * from the library class
         */
        TabPageIndicator indicator = (TabPageIndicator) findViewById(R.id.indicator);
        indicator.setViewPager(pager);  
like image 491
Rishabh Agrawal Avatar asked Oct 10 '12 16:10

Rishabh Agrawal


2 Answers

Be aware that the pager keeps at least one page ahead. Meaning that when the pager is created, he creates at least two pages - the one he shows and the next one, in order to allow "paging".

like image 118
gor Avatar answered Nov 15 '22 08:11

gor


In your getItem method you create a new instance of a fragment. This is terrible. It puts you in the situation you are in now. What you are doing is creating an new annynmous item that will live out it days as you specified. But when the evil Android system decides that is needs to talk to your Fragment again and requests it from your adapter, you are telling it "No. I don't wanna!" and instead giving it a new fragment EXACTLY the same as its older rother.

To fix this, you inflate all of your fragment ahead of time and then return the proper fragment. Or if you rather, don't. But keep a record of the instances you have created so you may return already created fragments.

I don't know exactly why its being called twice - I haven't scoured v4's source, but it is probably done to ensure that the item is actually retrieved or the system entered a state where the previous item needed to be refereshed.

In conclusion, retain created instances -especially for object as heavy as fragments, views and activities.

class Adapter extends MyWhateverAdapter {
    Fragment[] myLovelyFragments;

    public Adapter() {
        // Instantiate your fragments and place them into myLovelyFragments
    }

    public int getFragmentCount() {
        return myLovelyFragments.length;
    }

    public Fragment getItem(int position) {
        return myLovelyFragments[position];
    }
}
like image 38
ahodder Avatar answered Nov 15 '22 06:11

ahodder