web-dev-qa-db-fra.com

Android: FragmentPagerAdapter: méthode getItem appelée deux fois lors de la première fois

Dans mon application, j'ai utilisé le ViewPager. Comme,

(say main.xml)

<Android.support.v4.view.ViewPager
     Android:id="@+id/viewPager"
     Android:layout_width="fill_parent"
     Android:layout_height="fill_parent"
     Android:layout_above="@+id/register_header" />

Et créez un objet ViewPager et un objet ViewPagerAdapter (qui étend FragmentPagerAdapter) dans FragmentActivity.

_mViewPager = (ViewPager) findViewById(R.id.viewPager);

_adapter = new ViewPagerAdapter(getApplicationContext(),
         getSupportFragmentManager());

_mViewPager.setAdapter(_adapter);

Et la classe Adapter est comme,

public class ViewPagerAdapter extends FragmentPagerAdapter {
    private Context _context;
    private FragmentManager manager;
    private Fragment f;
    private String classname="ViewPagerAdapter";
    public ViewPagerAdapter(Context context, FragmentManager fm) {
        super(fm);  
        _context=context;
        manager=fm;
        }
    @Override
    public Fragment getItem(int position) {
        Log.i(classname,"getItem called"+position);
        f = new Fragment();
        f=MyFragment.newInstance();
        Bundle args = new Bundle();
        args.putInt("position", position);
        f.setArguments(args);
        return f;
    }

    @Override
    public int getCount() {
        return User.getPageCount();
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

Et dans la classe MyFragment,

Dans onResume, je dois stocker l'objet wigets dans la variable statique commune.

public void onResume() {
        super.onResume();
        pageIndex = getArguments().getInt("position");      
        User.useTextview1=textview1;
        User.useTextview2= textview2;
        User.current_pageIndex=pageIndex;



    }

Je dois mettre à jour les vues textuelles obtenues de la classe User dans FragmentActivity. Mon problème est que la méthode getItem () est appelée deux fois la première fois En fait, la vue affichée dans l'émulateur est le 0ème index, mais a obtenu la valeur du 1er Index dans FragmentActivity. Si j'arrêtais d'appeler la méthode getItem () une deuxième fois, je pourrais obtenir la référence TextView 0e index dans FragmentActivity.

S'il vous plaît, donnez-moi le meilleur moyen de le faire.

Merci

21
Sridhar

La FragmentPagerAdapter instancie 2 Fragments au début, pour l'index 0 et pour l'index 1. Si vous souhaitez obtenir des données à partir de la Fragment affichée, vous pouvez utiliser setOnPageChangeListener pour la Pager pour obtenir la position actuelle. Ensuite, ayez SparseArray avec WeakReference à vos fragments. Mettez à jour ce tableau dans l'appel getItem. Lorsque onPageSelected est appelé, utilisez cette position pour obtenir une référence à right Fragment et mettre à jour les données User.

Initialisation du tableau:

private SparseArray<WeakReference<MyFragment>> mFragments = new SparseArray<WeakReference<MyFragment>>(3);
17
Niko

Mon problème est que la méthode getItem () est appelée deux fois la première fois

Ce n'est pas le problème, c'est default feature of FragmentPagerAdapter. Il est bon que vous glissiez de cette page à la suivante et à la précédente.

la vue affichée dans l'émulateur est 0 index, mais obtient la première valeur d'index dans FragmentActivity

J'ai le même problème et je sais pourquoi. Ceci parce que vous used same Fragment in View Pager.

Comment résoudre ce problème est separate Fragments by using different Fragment.

1
Huy Tower

dans la méthode getItem j'ai écrit ceci ..

@Override
public Fragment getItem(int index) {
    EditFragment frag = new EditFragment();
    Bundle args = new Bundle();
    args.putSerializable("currentItem", itemsList.get(index));
    frag.setArguments(args);
    return (frag);
}

ici itemsList.get (index) est l'objet de classe de modèle que je vais utiliser dans la classe EditFragment. voici ça.

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
    View result = inflater.inflate(R.layout.pager_fragment_layout, container, false);
    image = (ImageView)result.findViewById(R.id.pager_image);
    text = (TextView)result.findViewById(R.id.pager_item_desc);
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity()).build();
    ImageLoader.getInstance().init(config);
    imLoader = ImageLoader.getInstance();

            ****NOTE
    final SwapItems itemList = (SwapItems) getArguments().getSerializable("currentItem");

    imagePath = itemList.getPaths().get(0);
    imLoader.displayImage(imagePath,image);
    text.setText(itemList.getItemDescription());

    image.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Fragment fragment = new ItemImagesFragment();
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            Bundle bundle = new Bundle();
            bundle.putSerializable("val", itemList);
            fragment.setArguments(bundle);
            fragmentTransaction.replace(R.id.content_frame, fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
        }
    });
    return result;
}

NOTE: ici, je reçois l'objet modèle swapitems de la méthode getItem précédente est 'final'. cela résout mon problème. Auparavant, j'avais initialisé le même objet avec static en tant que modificateur.

espère que le tien disparaîtra aussi

1
GvSharma

J'ai rencontré le même problème - la méthode getItem () a été appelée deux fois. Je ne sais pas si vous avez utilisé cette méthode pour déclencher des changements dans une activité d'hébergement lorsque de nouvelles diapositives apparaissent.

Tout d’abord, getItem () n’est pas une bonne méthode pour obtenir l’apparition d’une nouvelle diapositive.

J'ai utilisé l'écouteur ViewPager.OnPageChangeListener sur ViewPager lui-même à cette fin. Voici ce que j'ai fait:

Dans Activité contenant des fragments de diapositive:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.signature_wizard_activity);

    // Instantiate a ViewPager and a PagerAdapter.
    mPager = (ViewPager) findViewById(R.id.pager);
    mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
    mPager.setAdapter(mPagerAdapter);
    mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            onSlideChanged(position); // change color of the dots
        }
        @Override
        public void onPageSelected(int position) {}
        @Override
        public void onPageScrollStateChanged(int state) {}
    });
}

onPageScrolled () est appelée à chaque fois que votre diapositive apparaît. En tant que paramètre, elle obtient la position actuelle de la diapositive affichée. La bonne chose est qu'il s'appelle y compris la première fois qu'il apparaît, pas seulement quand la diapositive a été changée.

Quand peut-on l'utiliser? Par exemple, si vous avez une activité d’assistant avec ViewPager dans laquelle vous faites glisser des fragments avec quelques astuces, vous voudriez probablement avoir une barre avec des points gris au-dessous du curseur qui représenterait le nombre total de diapositives, et l’un des points être de couleur différente représentant la diapositive actuelle. Dans ce cas, ViewPager.OnPageChangeListener et la méthode onPageScrolled () seront la meilleure option.

Ou si vous avez des boutons PREV. et NEXT qui changent de diapositives et que vous voulez désactiver PREV. sur la première diapositive et désactivez le bouton SUIVANT sur la dernière diapositive. Voici comment vous le faites dans la méthode onPageScrolled ():

 @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if(position == 0){
                prevBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_grey_500));
                prevBtn.setEnabled(false);
            }else{
                prevBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_blue));
                prevBtn.setEnabled(true);
            }

            if(position == NUM_PAGES -1){
                nextBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_grey_500));
                nextBtn.setEnabled(false);
            }else{
                nextBtn.setTextColor(ContextCompat.getColor(SignatureWizardActivity.this, R.color.main_blue));
                nextBtn.setEnabled(true);
            }
        }

où NUM_PAGES est une constante avec le nombre total de diapositives

0
Kirill Karmazin

vous pouvez utiliser cette méthode pour mettre à jour vos vues

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser) {
        // Fetch data or something...
    }
}
0
saurabh dixit