user2782067
user2782067

Reputation: 422

Removing Fragments from ViewPager

Currently, I have the ability to open a new fragment from a page of my application. I want to have 'pinned' recipes, which will stay there if the pin button is clicked.

Currently, I store an ArrayList of 'pinned' recipes, and generate a fragment for each item in this list whenever a fragment is opened for a recipe.

What I want to do, though, is have the ability to remove an item from this list by unchecking the pin button. Currently, the removing of items is extremely unreliable, and sometimes it will remove a different fragment, or not remove anything at all.

Adapter:

public class CookingRecipesPagerAdapter extends FragmentStatePagerAdapter {

private final List<CookingRecipeFragment> fragmentList = new ArrayList<>();
private final List<Recipe> fragmentRecipeList = new ArrayList<>();


public CookingRecipesPagerAdapter(FragmentManager fm) {
    super(fm);
}

public void addFragment(CookingRecipeFragment fragment, Recipe recipe){
    fragmentList.add(fragment);
    fragmentRecipeList.add(recipe);
}

public CookingRecipeFragment getFragment(int position) {
    return fragmentList.get(position);
}

@Override
public Fragment getItem(int position) {
    return fragmentList.get(position);
}

@Override
public int getCount() {
    return fragmentList.size();
}

public Recipe getRecipe(int position) {
    return fragmentRecipeList.get(position);
}

public void removeItemAtPosition(int position){
    fragmentList.remove(position);
    fragmentRecipeList.remove(position);
    notifyDataSetChanged();
}

Fragment generating code:

        for(int i = 0; i < recipeList.size(); i++) {
        Recipe recipe = recipeList().get(i);
        CookingRecipeFragment fragment = new CookingRecipeFragment();
        Bundle bundl`enter code here`e = new Bundle();
        bundle.putInt("recipe",i);
        fragment.setArguments(bundle);
        adapter.addFragment(fragment,recipe);
    }

I have two button, nextButton and prevButton, to move through the fragments.

        public void onClick(View view) {
            removeCurrentRecipeIfUnpinned();
            try {
                viewPager.setCurrentItem(viewPager.getCurrentItem()+1);
            }
            catch (IndexOutOfBoundsException e){
                //
            }
        }

Here is how i attempt to delete the fragment and item when its not in use

public void removeCurrentRecipeIfUnpinned(){
    int index = viewPager.getCurrentItem();
    final CookingRecipesPagerAdapter adapter = ((CookingRecipesPagerAdapter)viewPager.getAdapter());
    CookingRecipeFragment fragment = adapter.getFragment(index);

    if (!fragment.getPinned()){
        adapter.removeItemAtPosition(index);
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            public void run() {
                adapter.notifyDataSetChanged();
            }
        });
    }
}

I previously tried to call some deleting function in the onStop() method, but this didn;t work, as the lifecycle of onStop() proved unsuitable. I was unable to find any method to override which is called at the appropriate time.

Upvotes: 2

Views: 114

Answers (1)

Khaled Lela
Khaled Lela

Reputation: 8139

Try this

private class CookingRecipesPagerAdapter extends FragmentPagerAdapter {

    final SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

    public CookingRecipesPagerAdapter() {
        super(getChildFragmentManager());
    }

    @Override
    public Fragment getItem(final int pos) {
        CookingRecipeFragment fragment = new CookingRecipeFragment();
        Bundle bundle = new Bundle();
        bundle.putInt("recipe",i);
        fragment.setArguments(bundle);
        return fragment;
    }

    /**
     * Implementing this method is IMPORTANT for detorying the fragment.
     * Use unique id for each item on pagerData.
     */
    @Override
    public long getItemId(int position) {
        return fragmentRecipeList.get(position).getId(); // Unique id by position and question id. 
    }


    @NonNull
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }

    @Override
    public int getCount() {
        return fragmentRecipeList.size();
    }
}

Update 1

protected Fragment getCurrentFragment() {
    if (pager.getAdapter() instanceof CookingRecipesPagerAdapter)
        return ((CookingRecipesPagerAdapter) pager.getAdapter()).getRegisteredFragment(currentIndex);
    return null;
}

public void removeCurrentRecipeIfUnpinned(){
    int index = viewPager.getCurrentItem();
    fragmentRecipeList.remove(index);
    adapter.notifyDataSetChanged();
}

Upvotes: 1

Related Questions